首页 > Python基础教程 >
-
C#教程之委托(delegate)(3)
委托揭秘
1 public delegate int MulticastInstance(int inputA, int inputB);
事实上通过反编译可看到:
编译器相当于定义了一个完整的类(继承自System.MulticastDelegate,定义四个方法:构造函数、Invoke、BeginInvoke和EndInvoke):
1 internal class MulticastInstance : System.MulticastDelegate//继承System.MulticastDelegate 2 { 3 //构造器 4 public MulticastInstance(object @object, IntPtr method); 5 //这个方法的原型和源代码指定的一样 6 public virtual int Invoke(int inputA, int inputB); 7 //实现回调方法和异步回调 8 public virtual IAsyncResult BeginInvoke(int inputA, int inputB, AsyncCallback callback, object @object); 9 public virtual int EndInvoke(IAsyncResult result); 10 } 11 /* 12 * 作者:Jonins 13 * 出处:http://www.cnblogs.com/jonins/ 14 */
所有委托类型都派生自System.MulticastDelegate类,System.MulticastDelegate派生自System.Delegate,后者又派生自System.Object。历史原因造成有两个委托类。
创建的所有委托类型豆浆MulticastDelegate作为基类,个别情况下仍会用到Delegate。Delegate类的两个静态方法Combine和Remove的签名都指出要获取Delegate参数。由于创建的委托类型派生自MulticastDelegate,后者又派生自Delegate,所以委托类型的实例是可以传递给这两个方法的。
MulticastDelegate的三个重要非公共字段
字段 | 类型 | 说明 |
_target | System.Object |
当委托对象包装一个静态方法时,这个字段为null。当委托对象包装一个实例方法时,这个字段引用的是回调方法要操作的对象。 当委托对象包装一个实例方法时,这个字段引用的是回调方法要操作的对象。换言之 换言之,这个字段指出要传给实例方法的隐士参数的值。 |
_methodPtr | System.IntPtr |
一个内部的整数值,CLR用它标记要回调的方法。 |
_invocationList | System.Object | 该字段通常为null,构造委托链时它引用一个委托数组。 |
Delegate反编译后可看到静态方法Combine和Remove(委托的+、-、+=、-=编译后的本质):
1 [Serializable, ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true), __DynamicallyInvokable] 2 public abstract class Delegate : ICloneable, ISerializable 3 { 4 [ComVisible(true), __DynamicallyInvokable] 5 public static Delegate Combine(params Delegate[] delegates); 6 [__DynamicallyInvokable] 7 public static Delegate Combine(Delegate a, Delegate b); 8 [SecuritySafeCritical, __DynamicallyInvokable] 9 public static Delegate Remove(Delegate source, Delegate value); 10 }
结语
同步委托将阻塞当前线程,等待方法执行完毕继续执行程序,相当于直接调用方法。异步委托是将方法放入线程池中执行并不阻塞主线程。异步委托从根本上说并不是多线程技术(任务Task也一样),就算异步委托内部将方法塞给线程池去执行也并不能说是开辟新线程执行方法,(线程池一定开辟新线程)这种说法并不严谨。委托本质是将调用者和目标方法动态关联起来,这是或许是我所理解的委托存在的最根本目的吧。