说说Delegate和Event
Delegate和Event,在C#中,常常看到他们在一起使用,这其中有什么奥秘呢,在这里我说说我看到的,我们以下边的代码为例:
1using System;
2
3//Delegate
4delegate void UpdateDelegate();
5
6//Subject
7class Subject
8{
9 public event UpdateDelegate UpdateHandler;
10
11 // Methods
12 public void Attach(UpdateDelegate ud)
13 {
14 UpdateHandler += ud;
15 }
16
17 public void Detach(UpdateDelegate ud)
18 {
19 UpdateHandler -= ud;
20 }
21
22 public void Notify()
23 {
24 if (UpdateHandler != null) UpdateHandler();
25 }
26
27}
28public class Client
29{
30 static void UpdateDelegateMethod()
31 {
32 Console.WriteLine("hello world");
33 }
34
35 public static void Main(string[] args)
36 {
37 Subject sj = new Subject();
38 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
39 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
40 sj.Notify();
41 }
42}
类Subjuect中的委托(UpdateDelegate)之前有event关键字,它的IL视图为:2
3//Delegate
4delegate void UpdateDelegate();
5
6//Subject
7class Subject
8{
9 public event UpdateDelegate UpdateHandler;
10
11 // Methods
12 public void Attach(UpdateDelegate ud)
13 {
14 UpdateHandler += ud;
15 }
16
17 public void Detach(UpdateDelegate ud)
18 {
19 UpdateHandler -= ud;
20 }
21
22 public void Notify()
23 {
24 if (UpdateHandler != null) UpdateHandler();
25 }
26
27}
28public class Client
29{
30 static void UpdateDelegateMethod()
31 {
32 Console.WriteLine("hello world");
33 }
34
35 public static void Main(string[] args)
36 {
37 Subject sj = new Subject();
38 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
39 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
40 sj.Notify();
41 }
42}
如果我们把委托(UpdateDelegate)之前的event关键字去掉,它的IL视图为:
两幅图对比之下,我们就会发现,加上Event关键之和去掉Event关键字所产生的IL代码大不相同。
我们再来看看Main函数中使用的不同
如果我们去掉委托(UpdateDelegate)之前的event关键字,下边Main方法中的写法都是对的,在编译的时候不会报错。
1 public static void Main(string[] args)
2 {
3 Subject sj = new Subject();
4 sj.UpdateHandler = UpdateDelegateMethod;
5 sj.UpdateHandler = new UpdateDelegate(UpdateDelegateMethod);
6 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
7 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
8 sj.Notify();
9 }
如果我们在委托(UpdateDelegate)之前加上event关键字2 {
3 Subject sj = new Subject();
4 sj.UpdateHandler = UpdateDelegateMethod;
5 sj.UpdateHandler = new UpdateDelegate(UpdateDelegateMethod);
6 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
7 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
8 sj.Notify();
9 }
1 public static void Main(string[] args)
2 {
3 Subject sj = new Subject();
4 //加上event关键字,下边两段代码要报错
5 //事件“Subject.UpdateHandler”只能出现在 += 或 -= 的左边(从类型“Subject”中使用时除外)
6 //sj.UpdateHandler = UpdateDelegateMethod;
7 //sj.UpdateHandler = new UpdateDelegate(UpdateDelegateMethod);
8 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
9 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
10 sj.Notify();
11 }
C#中,delegate是multicast的。multicast就是delegate可以同时指向多个函数。一个multicast delegate维护着一个函数的list,如果我们没有用+=,而是直接把函数指派给了delegate,这样的话,其他已经钩上delegate的函数都被去掉了,从这里我们就可以看出,使用event可以防止我们直接把函数指派给delegate,从机制上保证了delegate函数链不被破坏。
2 {
3 Subject sj = new Subject();
4 //加上event关键字,下边两段代码要报错
5 //事件“Subject.UpdateHandler”只能出现在 += 或 -= 的左边(从类型“Subject”中使用时除外)
6 //sj.UpdateHandler = UpdateDelegateMethod;
7 //sj.UpdateHandler = new UpdateDelegate(UpdateDelegateMethod);
8 sj.UpdateHandler += new UpdateDelegate(UpdateDelegateMethod);
9 sj.Attach(new UpdateDelegate(UpdateDelegateMethod));
10 sj.Notify();
11 }