zoukankan      html  css  js  c++  java
  • Demystifying Delegates

    首先瞅一下委托的定义:

    public delegate void Feedback(object value);

    编译器将之翻译后的代码:

    public class Feedback:System.MulticastDelegate
    {
      //构造函数
      public Feedback(object target,Int32 methodPtr);
      //委托对象调用回调函数的方法
      public void virtual Invoke(object value);
      //用于委托对异步回调的支持
      public virtual IAsyncResult BeginInvoke(object value,AsyncCallback callback,Object object);
      public virtual void EndInvoke(IAsyncResult result);
    }

    从编译器生成的源码可以看出:委托类 Feedback继承自System.MulticastDelegate,MulticastDelegate的有三个重要私有字段是_target(指向回调函数被调用时操作的对象,该字段用于实例方法的回调,如果是静态方法为NULL),_methodPtr(用于标识指定的回调方法),_prev(指向另一个委托对象,用于形成委托链)。_target 和 methodPtr两个参数在委托构造函数中被初始化。委托对象就是对方法及调用时操作的对象的一个封装。Invoke方法的返回值类型及参数与委托签名一致,使用_target和_methodPtr来确定在指定对象上调用指定的方法。MulticastDelegate提供了两个公共只读属性Target和Method,用于获取委托的封装信息。一个类期望调用另一个类的私有方法,可以通过将该私有方法做一个委托封装来实现。

    Delegate与MulticastDelegate间的关系

    System.MultiCastDelegate继承自System.Delegate,.net框架起初设计是两种委托类型:single-cast,multicast,delegate被设计成一个基类型,用于实现回调一个方法所必要的功能,而multicastDelegate用于支持委托对象链表,即void返回值原型方法的委托链。而在.net框架开发周期的后期,发现一些的缺陷,如一些情况下方法的返回值是非void值,但返回值可以忽略,但却不可以放到委托链中。鉴于多种限制,.net框架组后期在编译器上将这两个类进行了合并,为了支持委托链,编译器产生的委托类都继承自MutlicastDelegate。

    委托链的形成

    委托链即指一个MulcastDelegate对象指向另一个MulticastDelegate对象的引用,形成一个链表,利用的是MulticastDelegate字段_prev。

    Class System.Delegate{
    //head是最后一个被调用的委托对象
    public static Delegate Combine(Delegate tail,Delegate head);
    
    public static Delegate Combine(Delegate[] delegateArray);
    
    public static Delegate Remove(Delegate source,Delegate value);
    }

    当构造一个新的委托对象时,其_prev=null,利用combine形成委托链,新添加的委托对象位于委托链表的head,而它的_prev字段指向原委托链的head。调用一个委托对象会导致它前面的委托首先被调用,在调用前面的委托之后,委托对象才会调用自己封装的回调目标及回调方法(head是最后一个被调用的委托对象)。调用委托对象时实则是对该委托类型的Invoke方法的调用。委托对象一旦被构造,它们就认为是恒定不变的,也就是说在调用combine将一个委托对象给合到一个委托链中时,内部会构造一个新的委托对象,但是其_prev字段指向原委托链的head。

  • 相关阅读:
    javascript循环结构练习
    个人复习JavaScript重点(总结一)
    第十章汽车租凭系统
    员工执行
    第六章预习
    第五章使用Dictionary替换List<t>实现功能
    第5章体检套餐管理系统
    JAVA面试题
    AJAX
    SSM中的登陆验证码
  • 原文地址:https://www.cnblogs.com/spirit/p/1561541.html
Copyright © 2011-2022 走看看