仅供自己学习用。参考:张子阳的博客 http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
什么是委托
首先要知道什么是委托,用最通俗易懂的话来讲,你就可以把委托看成是用来执行方法(函数)的一个东西。
如何使用委托
在使用委托的时候,你可以像对待一个类一样对待它。即先声明,再实例化。只是有点不同,类在实例化之后叫对象或实例,但委托在实例化后仍叫委托。
声明,如:

2



3

4


5

这就声明了一个委托,意义:任何一个返回值为double,且只有一个形参为double的函数,都可以用这个委托来调用。
注意:委托的声明位置在namespace里面,类的外面。其实,委托的声明也可以在类的里面,甚至是任何一个可以声明类的地方。
实例化:
首先我们要先有一个满足委托声明的方法,假设一个返回一个数的2倍的方法:

2



3

4



5

6

7

有了这样一个方法,我们就可以实例化一个委托了:
MathsOp operation = new MathsOp( MathsOperations.MultiplyBy2 );
在实例化一个委托时,要给它一个参数,这个参数就是委托执行的方法,它可以是静态方法,也可以是实例方法(这一点有别于函数指针,函数指针只能调用静态方法),如:
MathsOp operation = new MathsOp( new Class1().Method1 );
在实例化完一个委托之后,就可以用这个委托来调用方法了:
double result = operation( 1.23 );
例子代码:

2



3

4

5



6

7



8

9



10

11

12

13

14

15



16

17

18

19

20

21

22

23

多路广播委托
前面使用的委托只包含一个方法调用。调用委托的次数与调用方法的次数相同。如果要调用多个方法,就需要多次显示调用这个委托。其实委托也可以包含多个方法,这种委托就是多路广播委托。多路广播委托派生于System.MulticastDelegate,它的Combine方法允许把多个方法调用链接在一起,我们可以通过+=来向委托添加调用方法,也可以用-=删除其中的调用方法。如:

2



3

4



5

6



7

8

9

10

11

12



13

14

15

16

17

18

19

20

21



22

23

24



25

26

27

28

29

30

31

32

33

34

35

36

输出:
Multiplying by 2: 1.23 gives 2.46
Squaring: 1.23 gives 1.5129
Squaring: 1.23 gives 1.5129
注意,多路广播委托声明时必须返回void,否则返回值不知道应该送回什么地方。对此,我做了一个测试:如果不将委托的声明返回void,则返回值返回的是最后一个链入委托链的方法的返回值,编译不会出错。
为什么要用委托
使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。
什么是委托?
(1)委托就是一个指向指定格式(参数、返回值)的函数的指针;
(2)委托是一个类;
用法举例:
namespace @delegate
{
public delegate void GreetingDelegate(string name);
class Program
{
static void Main(string[] args)
{
//用法1:把委托当成参数传递
GreetPeople("pjh", ChineseGreeting);
//用法2:创建一个指向EnglishGreeting方法的委托对象(实际上,绕过了GreetPeople方法)
GreetingDelegate gd = new GreetingDelegate(EnglishGreeting);//请注意,这里的声明是不是象类?
gd("pjh");
Console.ReadLine();
//用法3:将多个方法,绑定到同一个委托
GreetingDelegate multGd;
multGd = EnglishGreeting;//赋值 注意,与方法2使用关键字new声明不同,为什么?
multGd += ChineseGreeting;//绑定
multGd("pjh");
Console.ReadLine();
}
//注意此方法,它接受一个GreetingDelegate类型的方法作为参数
private static void GreetPeople(string name, GreetingDelegate MakeGreeting)
{
MakeGreeting(name);
}
private static void EnglishGreeting(string name)
{
Console.WriteLine("Morning, " + name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("早上好, " + name);
}
}
}
委托做一个总结:
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
可以将多个方法,绑定到同一个委托,如下:
GreetingDelegate delegate1;
delegate1 = EnglishGreeting; // 先给委托类型的变量赋值
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法
GreetPeople("Jimmy Zhang", delegate1);
Console.ReadKey();
我们也可以使用下面的代码来这样简化这一过程:(请参考例子中的方法2和方法3)
GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
看到这里,应该注意到,这段代码第一条语句与实例化一个类是何其的相似,你不禁想到:上面第一次绑定委托时不可以使用“+=”的编译错误,或许可以用这样的方法来避免:
GreetingDelegate delegate1 = new GreetingDelegate();
delegate1 += EnglishGreeting; // 这次用的是 “+=”,绑定语法。
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
但实际上,这样会出现编译错误: “GreetingDelegate”方法没有采用“0”个参数的重载。尽管这样的结果让我们觉得有点沮丧,但是编译的提示:“没有0个参数的重载”再次让我们联想到了类的构造函数。我知道你一定按捺不住想探个究竟,但再此之前,我们需要先把基础知识和应用介绍完。
既然给委托可以绑定一个方法,那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”:
static void Main(string[] args) {GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法
GreetPeople("Jimmy Zhang", delegate1);
Console.WriteLine();
delegate1 -= EnglishGreeting; //取消对EnglishGreeting方法的绑定
总结:
使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时(这里用“调用”这个词,是因为此变量代表一个方法),可以依次调用所有绑定的方法。