参考链接:
https://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
https://www.cnblogs.com/JimmyZhang/archive/2008/08/22/1274342.html
1.委托
a.定义一个委托就是定义一个类(委托会在编译的时候被编译成类)。因为委托是一个类,所以可以在任何可以声明类的地方来声明委托
b.委托定义了方法的类型,使得可以将方法当作参数来传递
c.可以将多个方法绑定到同一个委托变量,当调用该变量时,会依次调用所有绑定的方法
1 using System; 2 3 namespace ConsoleApp1 4 { 5 public delegate void GreetingDelegate(string name); 6 7 class Program 8 { 9 private static void EnglishGreeting(string name) 10 { 11 Console.WriteLine("Morning, " + name); 12 } 13 14 private static void ChineseGreeting(string name) 15 { 16 Console.WriteLine("早上好, " + name); 17 } 18 19 private static void GreetPeople(string name, GreetingDelegate MakeGreeting) 20 { 21 MakeGreeting(name); 22 } 23 24 static void Main(string[] args) 25 { 26 GreetingDelegate delegate1; 27 delegate1 = EnglishGreeting; // 先给委托类型的变量赋值 28 delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法 29 30 // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法 31 GreetPeople("Jimmy Zhang", delegate1); 32 Console.ReadKey(); 33 34 //输出为: 35 //Morning, Jimmy Zhang 36 //早上好, Jimmy Zhang 37 } 38 } 39 }
2.事件
a.事件是对委托的封装
如下,对于这样的一个事件:
public event GreetingDelegate MakeGreet;
会被编译成:
private GreetingDelegate MakeGreet; //对事件的声明 实际是 声明一个私有的委托变量 [MethodImpl(MethodImplOptions.Synchronized)] public void add_MakeGreet(GreetingDelegate value){ this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value); } [MethodImpl(MethodImplOptions.Synchronized)] public void remove_MakeGreet(GreetingDelegate value){ this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value); }
即一个事件,被编译后会产生一个private的委托变量,还有2个方法用于注册和取消注册委托(即+=和-=,这2个方法的访问权限等同于该事件的访问权限,事件为public即2个方法也为public)
例子:
1 using System; 2 3 namespace ConsoleApp1 4 { 5 public delegate void GreetingDelegate(string name); 6 7 public class GreetingManager 8 { 9 public event GreetingDelegate MakeGreet; 10 11 public void GreetPeople(string name) 12 { 13 MakeGreet(name); 14 } 15 } 16 17 class Program 18 { 19 private static void EnglishGreeting(string name) 20 { 21 Console.WriteLine("Morning, " + name); 22 } 23 24 private static void ChineseGreeting(string name) 25 { 26 Console.WriteLine("早上好, " + name); 27 } 28 29 static void Main(string[] args) 30 { 31 GreetingManager gm = new GreetingManager(); 32 gm.MakeGreet += EnglishGreeting; 33 gm.MakeGreet += ChineseGreeting; 34 35 gm.GreetPeople("Jimmy Zhang"); 36 Console.ReadKey(); 37 38 //输出为: 39 //Morning, Jimmy Zhang 40 //早上好, Jimmy Zhang 41 } 42 } 43 }
3.其他
a.委托和事件对应的是观察者模式,一对多的关系
b.委托和事件的区别在于,事件只能由事件发布者触发(即只能在定义事件所在的类内部触发),而委托则没有这个限制,委托类似于string,是一个变量的类型
c.委托定义的返回值通常为void,这是因为委托变量可以供多个订阅者注册,如果定义了返回值,那么多个订阅者的方法都会向发布者返回数值,结果就是后面一个返回的方法值将前面的返回值覆盖掉了,因此,实际上只能获得最后一个方法调用的返回值。所以返回订阅者的方法返回值大多数情况下根本没有必要