[C#]委托和事件

参考链接:

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,这是因为委托变量可以供多个订阅者注册,如果定义了返回值,那么多个订阅者的方法都会向发布者返回数值,结果就是后面一个返回的方法值将前面的返回值覆盖掉了,因此,实际上只能获得最后一个方法调用的返回值。所以返回订阅者的方法返回值大多数情况下根本没有必要

[C#]委托和事件

上一篇:Android 自定义圆圈进度并显示百分比例控件(纯代码实现)


下一篇:AcWing 7. 混合背包问题