分享

关于Delegate 和 MulticastDelegate的实现

 rongq2007 2021-02-10

在C#中,我们使用关键字delegate来定义委托,如:
public delegate void MyDelegate(object obj, int x);
在进行编译时,以上的代码将产生一个类定义:
public class MyDelegate : System.MulticastDelegate {
       public MyDelegate(Object target, IntPtr methodPtr);
       public void virtual Invoke(object obj, int x);     // 和委托中的参数一样.
       public virtual IAsyncResult BeginInvoke(object obj, int x, 
             AsyncCallback callback, object o);
       public virtual void EndInvoke(IAsyncResult result);
}
在以上代码中,构造函数中的参数:target 为对象实例的引用,methodPtr为用来标识回调方法。MulticastDelegate继承自Delegate,实际上Delegate类有四个私有字段:
1、private Object _target;
2、private IntPtr _methodPtr;
3、private IntPtr _methodPtrAux;
4、private RuntimeMethodInfo _method;
其中_target是调用方法的对象实例的引用,如果调用方法是static的,那么就不存在对象实例的引用,这时target为null。_methodPtr是用来标识要调用的方法。
在上面的MyDelegate委托中,MyDelegate的构造构数就是将_taget和_methodPtr进行初始化。

而 在MulticastDelegate类中,增加了一个私有字段:private MulticastDelegate _prev;这个_prev字段指向的是一个MulticastDelegate类型的引用,也就是说利用指向另一个MutlicastDelegate 类型的_prev字段来组成一个委托链表。
如果要向委托链表中增加和删除委托,C#中使用以下语法实现:
MyDelegate myDelegate = new MyDelegate(DelegateMethod1);
myDelegate += new MyDelegate(DelegateMethod2); //添加(Delegate.Combine) 
myDelegate -= new MyDelegate(DelegateMethod2); // 删除(Delegate.Remove)

在 新增一个委托到委托链表时,MyDelegate类的构造函数将调用基类MulticastDelegate的构造函数,将字段_target 和 _methodPtr初始化,并将MulticastDelegate的_prev字段初始化为null.在调用Remove方法时,它也会构造一个 MyDelegate的实例,也会初始化基类的_target、_methodPtr、和_prev字段。构造完后,Remove方法会先扫描委托链表, 如发现有和新创建的委托对象相等的委托对象,则将它从链表中删除,如没有找到,则不作做任何操作。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多