委托,注释翻译
(原文地址)https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/delegates/how-to-declare-instantiate-and-use-a-delegate
// 声明委托。
在 C# 1.0 和更高版本中,可以如下面的示例所示声明委托。
delegate void Del(string str); // 声明与委托具有相同签名的方法。 static void Notify(string name) { Console.WriteLine($"Notification received for: {name}"); } // 创建委托的实例。 Del del1 = new Del(Notify);
C# 2.0 提供了更简单的方法来编写前面的声明,如下面的示例所示。
// C#2.0提供了一种更简单的方法来声明Del的实例。
Del del2 = Notify;
在 C# 2.0 和更高版本中,还可以使用匿名方法来声明和初始化委托,如下面的示例所示。
// 使用匿名方法实例化Del。
Del del3 = delegate(string name)
{ Console.WriteLine($"Notification received for: {name}"); };
在 C# 3.0 和更高版本中,还可以通过使用 lambda 表达式声明和实例化委托,如下面的示例所示。
// 使用lambda表达式实例化Del。
Del del4 = name => { Console.WriteLine($"Notification received for: {name}"); };
//处理书店的一组类: namespace Bookstore { using System.Collections; // Describes a book in the book list: 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; } } // 声明用于处理书本的委托类型: public delegate void ProcessBookDelegate(Book book); // 维护图书数据库。 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) // 呼叫代表: processBook(b); } } } } // 使用书店类: namespace BookTestClient { using Bookstore; // 书籍的总价格和平均价格: class PriceTotaller { int countBooks = 0; decimal priceBooks = 0.0m; internal void AddBookToTotal(Book book) { countBooks += 1; priceBooks += book.Price; } internal decimal AveragePrice() { return priceBooks / countBooks; } } //类来测试图书数据库: class Test { // 打印书名。 static void PrintTitle(Book b) { Console.WriteLine($" {b.Title}"); } // 执行从这里开始。 static void Main() { BookDB bookDB = new BookDB(); // 使用一些书籍初始化数据库: AddBooks(bookDB); // 打印所有平装本的标题: Console.WriteLine("Paperback Book Titles:"); // 创建与静态 // 方法测试.打印标题: bookDB.ProcessPaperbackBooks(PrintTitle); // 使用PriceTotaller对象获取平装本的平均价格: PriceTotaller totaller = new PriceTotaller(); // 在对象汇总器上创建与非静态方法addBookTotal关联的新委托对象: bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal); Console.WriteLine("Average Paperback Book Price: ${0:#.##}", totaller.AveragePrice()); } // 使用一些测试手册初始化图书数据库: 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); } } }
/* Output: Paperback Book Titles: The C Programming Language The Unicode Standard 2.0 Dogbert's Clues for the Clueless Average Paperback Book Price: $23.97 */
可靠编程
-
声明委托。
以下语句声明新的委托类型。
public delegate void ProcessBookDelegate(Book book);
每个委托类型描述自变量的数量和类型,以及它可以封装的方法的返回值类型。 每当需要一组新的自变量类型或返回值类型,则必须声明一个新的委托类型。
-
实例化委托。
声明委托类型后,则必须创建委托对象并将其与特定的方法相关联。 在上例中,你通过将
PrintTitle方法传递给ProcessPaperbackBooks方法执行此操作,如下面的示例所示:bookDB.ProcessPaperbackBooks(PrintTitle);
这将创建一个新的与静态方法
Test.PrintTitle关联的委托对象。 同样,如下面的示例所示,传递对象AddBookToTotal中的非静态方法totaller:bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
在这两种情况下,都将新的委托对象传递给
ProcessPaperbackBooks方法。创建委托后,它与之关联的方法就永远不会更改;委托对象是不可变的。
-
调用委托。
创建委托对象后,通常会将委托对象传递给将调用该委托的其他代码。 委托对象是通过使用委托对象的名称调用的,后跟用圆括号括起来的将传递给委托的自变量。 下面是一个委托调用示例:
processBook(b);
委托可以同步调用(如在本例中)或通过使用
BeginInvoke和EndInvoke方法异步调用。

浙公网安备 33010602011771号