delegate委托
delegate委托:
三个概念: C# 中的委托类似于 C 或 C++ 中的函数指针。 委托是面向对象、类型安全的,并且是安全的。 委托和接口的类似之处是:它们都允许分隔规范和实现。 一个原则: 被托管函数的返回和参数必须和声明的托管相同; 基于这三个概念来看这个例子,这是微软的教程上讲的一个例子:
示例阐释声明、实例化和使用委托。BookDB 类封装一个书店数据库,它维护一个书籍数据库。它公开 ProcessPaperbackBooks 方法,该方法在数据库中查找所有平装书,并为每本书调用一个委托。所使用的 delegate 类型称为 ProcessBookDelegate。Test 类使用该类输出平装书的书名和平均价格。
委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书进行什么处理。
using System;
namespace Bookstore { using System.Collections; //1 声明Book public struct Book { public string Title; // 书名 public string Author; // 作者 public decimal Price; // 价格 public bool Paperback; // 简装 //构造函数 public Book(string title, string author, decimal price, bool paperBack) { Title = title; Author = author; Price = price; Paperback = paperBack; } } //2 托管声明:注意参数是Book,返回值void public delegate void ProcessBookDelegate(Book book); //3 书库 public class BookDB { ArrayList list = new ArrayList(); public void AddBook(string title, string author, decimal price, bool paperBack) { list.Add(new Book(title, author, price, paperBack)); } public void ProcessPaperbackBooks(ProcessBookDelegate processBook) { foreach (Book b in list) { if (b.Paperback) //12.processBook,他的调用和在运行是调用的就是PrintTitle() processBook(b); } } } } // 4 使用端
namespace BookTestClient { using Bookstore; // Class to total and average prices of books:
class PriceTotaller { int countBooks = 0; decimal priceBooks = 0.0m; //internal 修饰符使类、接口或成员仅在当前包中可见。 //当前包之外的代码不能访问 internal 成员。 //在全局范围内,internal 修饰符与 public 修饰符相同 internal void AddBookToTotal(Book book) { countBooks += 1; priceBooks += book.Price; } internal decimal AveragePrice()
{ return priceBooks / countBooks; } } //5.测试
class Test { // 打印书名 static void PrintTitle(Book b) { Console.WriteLine(" {0}", b.Title); } // 6 开始
static void Main() { //构造书库,这不必细说,从BookDB可以看很明白 BookDB bookDB = new BookDB(); // 7初始化书库,函数在往下找8
AddBooks(bookDB); // 10 打印所有平装书
Console.WriteLine("Paperback Book Titles:"); // 11.关键点到了,新建了一个托管对象,参数是Test.PrintTitle // 什么意思呢?先看PrintTitle(),他的参数和返回值和声明的托管 //要求的一致,我得理解是把这个函数的引用或者函数指针封装之后,当作参数 //交给函数ProcessPaperbackBooks 向上到12 bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle)); //13 同样的函数只要和委托在返回和参数上相同,就可以用了!
PriceTotaller totaller = new PriceTotaller(); bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
Console.WriteLine("Average Paperback Book Price: ${0:#.##}", totaller.AveragePrice()); } // 8 把书存到里面
static void AddBooks(BookDB bookDB) { bookDB.AddBook("The C Programming Language", "Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true); bookDB.AddBook("The Unicode Standard 2.0", "The Unicode Consortium", 39.95m, true); bookDB.AddBook("The MS-DOS Encyclopedia", "Ray Duncan", 129.95m, false); bookDB.AddBook("Dogbert's Clues for the Clueless", "Scott Adams", 12.00m, true); } } } 另外:委托对象的一个有用属性是,它们可以“+”运算符来组合。组合的委托可调用组成它的那两个委托。只有相同类型的委托才可以组合。
“-”运算符可用来从组合的委托移除组件委托。
// compose.cs using System; delegate void MyDelegate(string s);
class MyClass
{ public static void Hello(string s) { Console.WriteLine(" Hello, {0}!", s); } public static void Goodbye(string s)
{ Console.WriteLine(" Goodbye, {0}!", s); } public static void Main()
{ MyDelegate a, b, c, d; // Create the delegate object a that references
// the method Hello: a = new MyDelegate(Hello); // Create the delegate object b that references // the method Goodbye: b = new MyDelegate(Goodbye); // The two delegates, a and b, are composed to form c: c = a + b; // Remove a from the composed delegate, leaving d, // which calls only the method Goodbye: d = c - a; Console.WriteLine("Invoking delegate a:");
a("A"); Console.WriteLine("Invoking delegate b:"); b("B"); Console.WriteLine("Invoking delegate c:"); c("C"); Console.WriteLine("Invoking delegate d:"); d("D"); } } |


goodgoodstudy
博客统计信息
热门文章
最新评论
友情链接