什么是委托
委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示:
与委托的签名(由返回类型和参数组成)匹配的任何方法都可以分配给该委托。这样就可以通过编程方式来更改方法调用,还可以向现有类中插入新代码。只要知道委托的签名,便可以分配自己的委托方法。
将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,可以向排序算法传递对比较两个对象的方法的引用。分离比较代码使得可以采用更通用的方式编写算法。
用最通俗易懂的话来讲,你就可以把委托看成是用来执行方法(函数)的一个东西。
委托的使用
委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。下面的示例声明了一个名为 msg 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。
注意:委托的声明位置在namespace里面,类的外面。其实,委托的声明也可以在类的里面,甚至是任何一个可以声明类的地方。
构造委托对象时,通常提供委托将包装的方法的名称或使用匿名方法。实例化委托后,委托将把对它进行的方法调用传递给方法。调用方传递给委托的参数被传递给方法,来自方法的返回值(如果有)由委托返回给调用方。这被称为调用委托。可以将一个实例化的委托视为被包装的方法本身来调用该委托。例如:
publicstaticvoid DelegateMethod(string message)
{
System.Console.WriteLine(message);
}
msg handler = DelegateMethod;
// 调用委托.
handler("Hello World");
由于实例化委托是一个对象,所以可以将其作为参数进行传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息。此功能类似于接口所提供的封装。
回调的另一个常见用法是定义自定义的比较方法并将该委托传递给排序方法。它允许调用方的代码成为排序算法的一部分。下面的示例方法使用 msg 类型作为参数:
{
callback("The number is: "+ (param1 + param2).ToString());
}
然后可以将上面创建的委托传递给该方法:
在控制台中将收到下面的输出: The number is: 3
在将委托用作抽象概念时,MethodWithCallback 不需要直接调用控制台 -- 设计它时无需考虑控制台。 MethodWithCallback 的作用只是准备字符串并将该字符串传递给其他方法。此功能特别强大,因为委托的方法可以使用任意数量的参数。
多路广播委托
前面使用的委托只包含一个方法调用。调用委托的次数与调用方法的次数相同。如果要调用多个方法,就需要多次显示调用这个委托。其实委托也可以包含多个方法,这种委托就是多路广播委托。多路广播委托派生于System.MulticastDelegate,它的Combine方法允许把多个方法调用链接在一起,我们可以通过+=来向委托添加调用方法,也可以用-=删除其中的调用方法。如:
2{
4publicclass MyDelegate
5 {
6publicstaticvoid delegateMethod1( string str)
7 {
8 Console.WriteLine( "Hello,", str );
9 }
10
11publicstaticvoid delegateMethod2( string str)
12 {
13 Console.WriteLine( "你好,",str );
14 }
15 }
16class Start
17 {
18staticvoid Main(string[] args)
19 {
20 msg myMsg =new msg( MyDelegate.delegateMethod1);
21 myMsg +=new msg( MyDelegate.delegateMethod2);
22string str = "huangyuejun";
23 msg( str );
24
25 myMsg -=new msg( MyDelegate.delegateMethod2);
26 msg( str );
27
28 Console.Read();
29 }
30 }
31}
输出: Hello,huangyuejun 你好,huangyuejun Hello,huangyuejun
注意,多路广播委托声明时必须返回void,否则返回值不知道应该送回什么地方。对此,我做了一个测试:如果不将委托的声明 返回void,则返回值返回的是最后一个链入委托链的方法的返回值,编译不会出错。
为什么使用委托
使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。
C#委托之个人理解(http://www.cnblogs.com/michaelxu/archive/2008/03/31/1131500.html)
C#中的委托和事件(http://www.cnblogs.com/jimmyzhang/archive/2007/09/23/903360.html)
C#编程指南(http://msdn.microsoft.com/zh-cn/library/ms173171(v=VS.90).aspx)