委托与事件

  首先多谢网上的大牛们无私地分享自己的经验,让我这样的小鸟能站在巨人的肩膀上不断前进!

  参考网址:http://www.knowsky.com/395937.html(参考1)

                http://hi.baidu.com/zhangguilin/blog/item/9d34dc17a088ff0ac83d6d08.html(参考2)

                http://www.chinaz.com/program/2009/1014/94676.shtml(参考3)

  以下是我的总结:

委托                                                                    

  msdn把委托描述为面向对象、类型安全、可实现多播的函数指针。

  1、面向对象:.net把委托(函数指针)定义为类型,具体的类名为委托名称,并且存在继承关系:自定义委托<--System.MulticastDelegate<--System.Delegate。

  2、类型安全:委托对象中有_target、_methodPtr、_methodPtrAux三个变量。当委托实例指向某个实例方法时,_target指向实例对象,_methodPtr指向实例方法的JIT STUB(如果经过了JIT编译,就直接指向实例方法的内存地址),_methodPtAux为0;当委托实例指向某个静态方法时,_target指向委托实例本身,_methodPtr指向STUB(一小段代码,用于让CLR把_target设为null),_methodPtAux指向静态方法的内存地址。从上面可以看出委托实例中不仅保存了函数的地址,还保存了函数所在类的实例,相反看一下C++的函数指针只是保存函数的地址,而不管实例函数属于哪一个类。

  3、可实现多播:通过+=、—=添加(移除)函数指针。实例化委托时,MyDelegate d = new MyDelegate(my)为单播形式;MyDelegate d += new MyDelegate(my),d += new MyDelegate(my1)为多播形式。添加(移除)函数指针实际调用了MulticastDelegate的CombineImpl方法把函数指针添加到_invocationList(类型为object数组),可以同过委托实例.GetInvocationList()方法获取。

  注意:在多播情况,假如某些函数有返回值,那么要使用下列方式来获取返回值。

foreach(var item in 委托实例.GetInvocationList())
{
item();
}

并非像(参考2)里面说的多播中的函数不能有返回值。

 

事件                               

  事件跟委托有许多相似之处,经常不知道使用哪一个,这里着重说明两者的区别。这里参考了.NET委托: 一个C#睡前故事,这个例子描述得十分清楚。

  下面是自己的总结。

  委托对象定义为public后不仅所属类内部能调用,类外部也能调用;事件不管即使定义为public,也只能在所属类的内部触发,而类外部只能订阅不能触发事件。


总结                             

  使用事件可以降低耦合度,事件的触发与事件的订阅分离,让感兴趣的对象订阅某个对象的全部或部分事件。

posted @ 2012-01-18 17:45  ^_^肥仔John  阅读(518)  评论(0编辑  收藏  举报