码迷,mamicode.com
首页 > Windows程序 > 详细

通过IL分析C#中的委托、事件之间的区别与联系

时间:2015-05-04 13:54:56      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:c#   委托   事件   区别   联系   

一直以来都是对于事件与委托比较混淆,而且不太会用。找了个时间,总结了一下,感觉清晰了很多。

先说一下个人理解的结论吧:

      delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。

     delegate声明的变量与delegate声明的事件,并没有本质的区别,事件是在delegate声明变量的基础上包装而成的,类似于变量与属性的关系(在IL代码中可以看到每一个delegate声明的事件都对应是私有的delegate声明的变量),提升了安全性。

首先了解一下, ILDasm中图标含义:  

技术分享   

该图来自:http://www.cnblogs.com/zery/p/3366175.html

新建一个事件委托测试项目:EventDelegateTest

具体代码如下:

<span style="font-size:14px;">namespace EventDelegateTest
{
    public class TestClass
    {
        public delegate int delegateAction();
        public event delegateAction OnActionEvent;
        public delegateAction daNew;
    }
}</span>
编译代码后,使用 Visual Studio 2010自带的ILDASM.EXE:

技术分享

打开该dll,可以看到如下信息:

技术分享

从上图可以看出如下几点信息:
1、委托 public delegate int delegateAction();
      在IL中是以类(delegateAction)的形式存在的
2、public event delegateAction OnActionEvent;
      在IL中不仅仅对应event OnActionEvent而且还对应一个field OnActionEvent;
而field OnActionEvent与 public delegateAction daNew生成的field daNew是一样的
技术分享

技术分享

都是以字段(field )的形式存在的。
双击event OnActionEvent可以看到如下信息:
技术分享

在IL中事件被封装成了包含一个add_前缀和一个remove_前缀的的代码段。
其中,add_前缀的方法其实是通过调用Delegate.Combine()方法来实现的,组成了一个多播委托;remove_就是调用Delegate.Remove()方法,用于移除多播委托中的某个委托。
也就是说:事件其实就是一个特殊的多播委托
那么对于事件进行这一次封装有什么好处呢?
1、因为delegate可以支持的操作非常多,比如我们可以写onXXXChanged += aaaFunc,把某个函数指针挂载到这个委托上面,但是我们也可以简单粗暴地直接写onXXXChanged = aaaFunc,让这个委托只包含这一个函数指针。不过这样一来会产生一个安全问题:如果我们用onXXXChanged = aaaFunc这样的写法,那么会把这个委托已拥有的其他函数指针给覆盖掉,这大概不是定义onXXXChanged的程序员想要看到的结果。
小注:
    虽然事件不能直接=某个函数,但可以=null,此处需要注意
2、还有一个问题就是onXXXChanged这个委托应该什么时候触发(即调用它所包含的函数指针)。从面向对象的角度来说,XXX改变了这个事实(即onXXXChaned的字面含义)应该由包含它的那个对象来决定。但实际上我们可以从这个对象的外部环境调用onXXXChanged,这既产生了安全问题也不符合面向对象的初衷。 

参考文章:http://www.zhihu.com/question/28932542


通过IL分析C#中的委托、事件之间的区别与联系

标签:c#   委托   事件   区别   联系   

原文地址:http://blog.csdn.net/jiankunking/article/details/45479105

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!