漫谈委托和事件
委托和事件是C#中相当重要的部分,先简单科普一下这两个概念的定义:
委托delegate 关键字用于声明一个引用类型,该引用类型可用于封装命名方法或匿名方法。委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。——msdn
事件event是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。 如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处
理程序方法。事件可标记为 public、private、protected、internal 或protectedinternal。 这些访问修饰符定义类的用户访问事件的方式。——msdn
估计能真正理解这两段话的都是大牛,我辈菜鸟只能“噢,原来如此,还是不懂...” 最近菜鸟D在项目中使用到了委托,刚好有大牛路过,就请他帮忙诊断一下。
代码简化如下:
1 namespace abc{ 2 3 public delegate void xxxdelegate();//委托的声明 4 5 class abc 6 { 7 public xxxdelegate xxx; 8 9 public void a() 10 { 11 } 12 13 public void b() 14 { 15 } 16 17 public void c() 18 { 19 } 20 21 public void main() 22 { 23 ... 24 pd(); 25 xx(); 26 } 27 28 public void pd() 29 { 30 if () 31 { 32 xxx = a; 33 } 34 else if () 35 { 36 xxx = b; 37 } 38 else 39 { 40 xxx = c; 41 } 42 } 43 44 public void xx() 45 { 46 ... 47 xxx(); 48 } 49 } 50 }
大牛看完代码,皱了皱眉头,“委托不是这么用的啊...”
“委托不是一个安全的函数指针,可以把方法当成变量来使用的么?”菜鸟D不解。
“这么理解委托是不错的,但是它的应用场景不对啊,这些都是自己的方法,为什么不用一个判断,把判断的逻辑封装成方法,直接调用方法呢?这样看,你的委托是不是没有什么用?”大牛很耐心,“委托,委托,顾名思义应该执行的是别人的方法呀 。”
菜鸟D无话可说了,因为这么写只是在用“指针”的思想,而委托的本意却是被抛在了一边,“那么,委托的应用场景应该是什么?”。
“委托通常在处理异步线程时才会使用,而且它也是事件的基础。委托定义一种类型,事件可以看做这种类型的一个变量,你在反编译时也肯定见过,事件会被反编译成一个私有的委托以及 +=和-= 两个共有的方法供外部来使用。所以它的使用场景就很明显了,使用事件的时候,异步线程调用的时候。我建议你看看设计模式中的订阅发布模式。”
菜鸟D找了一下资料,发现各种资料说的乱七八糟,就在这时大牛给了一个很简单的例子,他指着电脑的USB口,“我不知道这里会插入什么设备,但是我定义了一个规格,只要符合这个规格,就可插进来。事件也是这样,假设是一个button,我不知道点击它会有什么效果,我就给它(button)封装一个点击事件,你只需要在外部注册这个事件,就可以让它在点击时有你想要的效果。spring的依赖注入也是这么回事,那个经常通过接口来注入,这个则是通过事件这个‘接口’或者叫‘插口’来实现,事件的内部又是委托,其实就是这么个关系。”
菜鸟D仔细想了想,结合原来的经验——在模态对话框或者主窗体和子窗体(并非是继承关系的父子窗体,而是由主窗体创建的)之间通信时会出现委托,至于上面代码的“指
针”确实是个笑话。
总结:委托的使用场景:异步进程和事件的使用。
订阅者模式:如果不太懂,可以参阅:http://blog.csdn.net/tjvictor/article/details/5223309
spring的依赖注入思想到下一篇再写,不好意思了。
菜鸟D希望这篇漫谈对您有所帮助。