首页 > 代码库 > 漫谈委托和事件
漫谈委托和事件
委托和事件是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 else39 {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希望这篇漫谈对您有所帮助。
漫谈委托和事件