zoukankan      html  css  js  c++  java
  • 委托

    1、概念

    回调函数是一种非常有用的编程机制,但是在在非托管的C/C++中,非成员函数的地址只是一个内存地址,不带任何额外的信息,因此非托管的回调函数是非类型安全的。而在.net下,提供了一种类型安全的回调机制:委托。委托可以回调静态方法、实例方法等。

    2、结构

    编译器和CLR实现委托是非常复杂的。它需要在幕后做很多工作。

    源代码:interna delegate void Feedback(int32 value);

    编译器编译结果:

    interna class Feedback:System.MulticastDelegate

    {

          //构造器

         public Feedback(Object object, IntPtr method);

         //方法原型和源代码指定相同

         public virtual void Invoke(Int32 value);

         //允许异步调用的方法

         public virtual IAsyncResult BeginInvoke(Int32 value,AsnycCallback, Object object);

         public virtual void EndInvoke(IAsncResult result);

    }

         编译器定义的类有4个方法:一个构造器、Invoke、BeginInvoke、EndInvoke。在这里,编译器生成类一个类Feedback,该类继承自MulticastDelegate(所有的委托都继承自该类)。System.MulticastDelegate继承自System.Delegate。在一些特殊情况下,我们会用到Delegate类。

         因为委托是一个类,所以可以在定义类的地方定义委托。

         所有的委托类型都继承自MulticastDelegate类,该类有3个非公共字段非常重要。

         _target(System.Object):当委托封装的是一个静态方法时,该字段为null,当委托对象封装一个实例方法时,该字段引用的是调用回调方法时要操作的对象。即这个字段指明要传给实例方法的隐式this的值。

         _methodPtr(System.IntPtr):一个内部的整数值,CLR用它来标识要回调的方法

         _invocationList(System.Object):该字段通常为null。在构造一个委托链时,它用来引用一个委托数组,委托链引用该数组的最后一个委托。

         所有的委托都有一个构造器,该函数有两个参数:一个对象引用和一个引用回调方法的整数。当定义委托时,因为C#编译器知道创建的是委托,他会对源代码进行解析约定引用的是那个对象和方法。对象引用被传递给object参数,标识方法的特殊IntPtr值别传给method参数。对于静态方法,null被传递给object参数。

         Delegate类定义了两个只读属性:Target和Method。给定一个对象引用,我们就可以查询这些属性。

    3、委托链

         链式委托是指有一些列委托对象组成的集合。它允许调用集合中各个委托所表示的所有方法。

         Delegate类的静态方法Combine用于添加一个委托到委托链。当调用该方法时,将会构造一个新的委托对象,该对象的_invocationList字段会被初始化为引用一个委托对象数组。该数组的最后一个索引会指向新添加的委托。同时该方法的返回值也会设置为引用新建的委托对象。

         Delegate类的静态方法Remove用于从委托链删除委托。

          C#编译器为委托类型提供了运算符+=和-=重载,这些运算符分别调用Delegate.Combine和Delegate.Remove。使用这些运算符简化了创建委托链的过程。

         MulticastDelegate类提供了一个实例方法:GetInvocationList,用来显示调用链中的每一个委托。

    4、C#编译器的便利

         C#编译器为委托提供了一些简便的方法,如匿名方法等。

    5、委托和反射

         为了使用委托,开发人员需要知道回调的方法的原型。但是有时候开发人员在编译时不知道这些信息。System.Delegate提供了几个方法,在编译时不知道委托的这些必要信息是,来创建并调用一个委托。

         CreateDelegate方法:创建委托。其中的MethodInfo参数最好用反射API来获取。如果是封装的实例方法,firstArgument指出要作为this参数传给这个实例方法的对象。

         DynamicInvoke:调用委托对象的回调方法。它传递一组在运行时才知道的参数。

        

  • 相关阅读:
    如何打开指定文件所在的文件夹并选中文件
    不阻止多线程中控件跨线程访问
    .NET使用并行计算 提高执行效率
    关于线程安全中Lock的一些说明
    多线程中调用多参数的方法
    C#把汉字转换成拼音
    跨窗体Invoke时使用匿名方法或者带参方法
    给MP3音乐文件写ID3信息和专辑封面
    用Python作GIS:菜谱篇
    python中对象self的由来
  • 原文地址:https://www.cnblogs.com/jyz/p/1421403.html
Copyright © 2011-2022 走看看