C#中的委托
本文整理微软官方文档:http://msdn.microsoft.com/zh-cn/library/ms173171
一、委托(delegate)
委托是一种定义方法签名的类型。 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。 您可以通过委托实例调用方法。委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法
public delegate int PerformCalculation(int x, int y);
与委托的签名(由返回类型和参数组成)匹配的任何可访问类或结构中的任何方法都可以分配给该委托。 方法可以是静态方法,也可以是实例方法。
二、何时使用委托而不使用接口
委托和接口都允许类设计器分离类型声明和实现。 任何类或结构都能继承和实现给定的接口。 可以为任何类上的方法创建委托,前提是该方法符合委托的方法签名。 接口引用或委托可由不了解实现该接口或委托方法的类的对象使用。 既然存在这些相似性,那么类设计器何时应使用委托,何时又该使用接口呢?
在以下情况下,请使用委托:
• 当使用事件设计模式时。
• 当封装静态方法可取时。
• 当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
• 需要方便的组合。
• 当类可能需要该方法的多个实现时。
在以下情况下,请使用接口:
• 当存在一组可能被调用的相关方法时。
• 当类只需要方法的单个实现时。
• 当使用接口的类想要将该接口强制转换为其他接口或类类型时。
• 当正在实现的方法链接到类的类型或标识时:例如比较方法。
三、如何:声明、实例化和使用委托
1.在 C# 1.0 及更高版本中,可以按以下示例所示声明委托。
delegate void Del(string str);
static void Notify(string name)
{
Console.WriteLine("Notification received for: {0}", name);
}
Del del1 = new Del(Notify);
2.C# 2.0 提供了更简单的方法来编写上面的声明,如以下示例所示。
Del del2 = Notify;
3.C# 2.0 及更高版本中,还可以使用匿名方法来声明和初始化委托,如以下示例所示。
Del del3 = delegate(string name)
{ Console.WriteLine("Notification received for: {0}", name); };
4.在 C# 3.0 及更高版本中,还可以使用 Lambda 表达式来声明和实例化委托,如以下示例所示。
Del del4 = name => { Console.WriteLine("Notification received for: {0}", name); };
四、完整的委托例子
// A set of classes for handling a bookstore:
namespace Bookstore
{
using System.Collections;
// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; // Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?
public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}
// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);
// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();
// Add a book to the database:
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}
// Call a passed-in delegate on each paperback book to process it:
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}
}
}
}
// Using the Bookstore classes:
namespace BookTestClient
{
using Bookstore;
// Class to total and average prices of books:
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 to test the book database:
class TestBookDB
{
// Print the title of the book.
static void PrintTitle(Book b)
{
System.Console.WriteLine(" {0}", b.Title);
}
// Execution starts here.
static void Main()
{
BookDB bookDB = new BookDB();
// Initialize the database with some books:
AddBooks(bookDB);
// Print all the titles of paperbacks:
System.Console.WriteLine("Paperback Book Titles:");
// Create a new delegate object associated with the static
// method Test.PrintTitle:
bookDB.ProcessPaperbackBooks(PrintTitle);
// Get the average price of a paperback by using
// a PriceTotaller object:
PriceTotaller totaller = new PriceTotaller();
// Create a new delegate object associated with the nonstatic
// method AddBookToTotal on the object totaller:
bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);
System.Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
totaller.AveragePrice());
}
// Initialize the book database with some test books:
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
*/
五、如何:合并委托(多路广播委托)
委托对象的一个有用属性是:可以使用 + 运算符将多个对象分配给一个委托实例。 多播委托包含已分配委托的列表。 在调用多播委托时,它会按顺序调用列表中的委托。 只能合并相同类型的委托。
- 运算符可用于从多播委托中移除组件委托。
using System;
// Define a custom delegate that has a string parameter and returns void.
delegate void CustomDel(string s);
class TestClass
{
// Define two methods that have the same signature as CustomDel.
static void Hello(string s)
{
System.Console.WriteLine(" Hello, {0}!", s);
}
static void Goodbye(string s)
{
System.Console.WriteLine(" Goodbye, {0}!", s);
}
static void Main()
{
// Declare instances of the custom delegate.
CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;
// In this example, you can omit the custom delegate if you
// want to and use Action<string> instead.
//Action<string> hiDel, byeDel, multiDel, multiMinusHiDel;
// Create the delegate object hiDel that references the
// method Hello.
hiDel = Hello;
// Create the delegate object byeDel that references the
// method Goodbye.
byeDel = Goodbye;
// The two delegates, hiDel and byeDel, are combined to
// form multiDel.
multiDel = hiDel + byeDel;
// Remove hiDel from the multicast delegate, leaving byeDel,
// which calls only the method Goodbye.
multiMinusHiDel = multiDel - hiDel;
Console.WriteLine("Invoking delegate hiDel:");
hiDel("A");
Console.WriteLine("Invoking delegate byeDel:");
byeDel("B");
Console.WriteLine("Invoking delegate multiDel:");
multiDel("C");
Console.WriteLine("Invoking delegate multiMinusHiDel:");
multiMinusHiDel("D");
}
}
/* Output:
Invoking delegate hiDel:
Hello, A!
Invoking delegate byeDel:
Goodbye, B!
Invoking delegate multiDel:
Hello, C!
Goodbye, C!
Invoking delegate multiMinusHiDel:
Goodbye, D!
*/
六、补充:
由于申明的委托是System.Delegate的子类,所有实体委托可以使用System。Delegate中分装的方法:Invoke
,Begin Invoke等
分享到:
相关推荐
委托(Delegate)和事件(Event)是C#中非常重要的两种机制,它们在.NET框架中扮演着极其重要的角色。理解这两种概念,对于深入学习C#编程语言,构建高效、可维护的程序架构至关重要。首先我们来探讨一下委托的概念...
委托、事件和BeginInvoke在C#中是实现进程间消息传递的重要概念和工具。委托可以理解为一个可以持有对具有特定参数列表和返回类型的方法的引用的类型。事件是一种特殊的委托,用于实现发布-订阅模式,其中发布者触发...
详细讲述了C#中委托和事件的语法及其使用方法,用程序例子深入浅出的讲述了不同的使用方法和这些使用方法的优劣。
在C#编程语言中,委托是类型安全的函数指针,允许我们传递方法作为参数,或者将多个方法关联起来形成回调机制。在Windows Forms应用程序中,委托常常被用来处理事件,使得用户界面(UI)与业务逻辑之间的通信更加...
在C#编程语言中,委托是面向对象设计的一个重要特性,它扮演着事件处理和回调函数的角色。本文将深入探讨委托的概念、用法以及在实际编程中的应用。 **委托概念** 委托在C#中可以被理解为一种类型,它代表了一个...
在C#编程语言中,委托是类型安全的函数指针,它允许我们传递方法作为参数,或者存储在变量中稍后调用。委托是.NET框架中的一个重要特性,它为实现事件处理、回调函数以及异步操作提供了强大的支持。在这个"C#中委托...
C# 中委托和事件的例子DelegateAndEventDemo 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA 源码 毕业设计 开题报告 答辩PPT等
### C#中的委托和事件:理解无多播委托 在.NET框架中,委托与事件是极为重要的编程概念,尤其在C#中它们被广泛应用于多种场景。本文将深入探讨C#中的委托、事件以及无多播委托的概念,并通过具体示例帮助读者更好地...
委托是C#中一个非常重要的概念,从C# 1开始就有了委托这个核心概念,在C# 2和C# 3中委托又有了很多改进。 通过委托,我们可以将一个方法当作对象封装起来,并且在运行时,我们可以通过这个对象来完成方法的调用。 ...
在C#编程语言中,委托是一种非常重要的特性,它允许我们定义类似于函数指针的类型,可以用来存储和调用方法。在这个简单的示例源码中,我们将深入探讨委托的概念,以及如何在C#中使用它们。对于初学者来说,理解委托...
事件(Event)在C#中是一种特殊的委托,它是类或对象发布消息或通知的方式,用于通知其他对象某个特定的事情已经发生。事件通常与委托结合使用,通过发布者(publisher)和订阅者(subscriber)模型工作。发布者定义...
本文将深入探讨C#委托的概念、用途、类型以及如何使用`DynamicInvoke`方法。 ### 1. 委托的基本概念 委托是C#中的一个类,它封装了指向方法的引用。换句话说,委托就像一个指针,但它指向的是方法而不是内存地址。...
在C#编程语言中,委托和事件是两个关键的概念,它们是实现事件驱动编程的核心机制。委托可以看作是类型安全的函数指针,允许我们传递方法作为参数,或者存储和调用方法。事件则是基于委托的一种通信机制,用于在对象...
在C#编程中,委托是一种强大的工具,它允许我们传递方法作为参数,或者将多个方法绑定到一个事件处理程序上。在这个"父窗体传值到子窗体,DEMO"中,我们可以深入理解委托如何在窗口之间的通信中起到关键作用。这个...
委托是C#语言中的一种类型,它定义了方法的类型,使得方法可以被传递。委托相当于C语言中的函数指针,可以将一个方法作为参数传递给另一个方法。委托在C#编程中起着非常重要的作用,它帮助我们实现了方法的参数化,...
在C#的委托是一种强大的机制,具有多种作用和优势: 1. 回调机制 委托允许将方法作为参数传递给其他方法,以实现回调机制。这种特性在事件处理、异步编程和多线程等场景下非常有用,允许程序在适当的时候调用预先...
在C#编程中,委托(Delegate)是一种强大的工具,它允许我们将方法作为参数传递,或者在运行时动态地组合方法。这种特性使得C#具备了函数式编程的一些元素,为事件处理、回调机制以及异步操作提供了便利。本文将深入...
在C#编程语言中,委托和事件是两个非常重要的概念,它们主要用于实现对象之间的通信,尤其是在处理异步操作和响应用户界面(UI)交互时。本文将深入探讨这两个概念,并通过一个实例来帮助理解它们的工作原理。 首先...
接下来,我们将基于提供的代码片段深入分析C#委托的另一种实现方式,并讨论其实现原理及其应用场景。 ### 委托的基本概念 委托在C#中是一种引用类型的数据结构,它定义了方法的类型,使得可以将方法当作另一个方法...