.net Delegate (二):揭秘

来源:互联网 发布:网络语雪梨是什么意思 编辑:程序博客网 时间:2024/06/07 04:58

.net中定义了2种不同类型的委托:单播委托System.Delegate和多播委托System.MulticastDelegate.  


System.MulticastDelegate继承自System.Delegate。 System.Delegate用于不可以被链接在一起的委托对象;MulticastDelegate可以链接多个委托对象。



而在实际中,我们创建的所有委托类型都是以MulticastDelegate为基类的。(因为MulticastDelegate继承自Delegate,后者的2个静态方法Combine和Remove也经常使用。)
由此可知,我们创建的委托都允许维护一个委托链表,将回调方法或者说此委托类型的实例放到委托链表中。通过重载的操作符:+=和-=可以完成上链和移除的操作,其背后就是调用Combine和Remove方法。

在class MouseFamily中定义的委托:
    class MouseFamily    {        //定义Feedback委托类型        public delegate void Feedback(string mouseName, int num);        private string[] mice;        public MouseFamily(string[] mouseName)        {            mice=new string[mouseName.Length];            for (int i = 0; i < mouseName.Length; i++)                mice[i] = mouseName[i];        }        public void Run(Feedback feedback)        {            for (int i = 0; i < mice.Length; i++)            {                if (feedback != null)                    feedback(mice[i], i + 1);            }        }    }

编译器遇到public delegate void Feedback(string mouseName, int num);这句时,会产生如下一个类的定义:

     public class Feedback : System.MulticastDelegate {            //构造函数            public Feedback(Object target,Int32 methodPtr);            //类似于函数的签名,和原型函数一致            public void virtual Invoke(string mouseName,Int32 num);            //允许进行异步的回调            public virtual IAsyncResult BeginInvoke(string mouseName,                Int32 num,                AsyncCallback callback,Object object);            //等待异步的返回            public virtual void EndInvoke(IAsyncResult result);        }
ILDasm查看:


Delegate类有四个私有字段:
1、private Object _target;
2、private IntPtr _methodPtr;
3、private IntPtr _methodPtrAux;
4、private RuntimeMethodInfo _method;
其中_target是调用方法的对象实例的引用,如果调用方法是static的,那么就不存在对象实例的引用,这时target为null。_methodPtr是用来标识要调用的方法(一个特殊的标识方法的Int32值)
在上面的Feedback委托中,Feedback的构造构数就是将_taget和_methodPtr进行初始化。


MulticastDelegate类自己增加了个私有字段:
private  MulticastDelegate _prev;
_prev用于指向另一个委托对象,实现链表。


当回调方法时,feedback+=new MouseFamily.Feedback(Tom.Cry)
回调方法产生的代码像编译下面的代码一样
feedback.Invok(mouseName,num);

原创粉丝点击