委托时一种特殊的类型,它用来保存方法的地址,这样我们很方便的调用方法,像变量一样传递,回调。
C++中的函数指针也是保存方法的地址,但是有一点不一样的是定义委托的时候就知道了它里面可以保存什么样的方法,而函数指针就没有这些
所以委托相对更明确一点,更安全一点。
public delegate void MyDelegate(int x) //这样的委托类型表示,该委托可以用来保存无返回值,切参数为int类型的方法
当然当我们写出上面那段代码的时候,实际上编译器做了其他一些事,实际可能定义像下面这样的
public class MyDelegate:system.MusticastDelegate { public MyDelegate(object obj,IntPtr method){……} //obj保存,方法的实例(静态方法则null),IntPtr保存方法地址 public virtual void Invoke(int value){……} //调用方法 ……//省略 }
MusticastDelegate 内部有
_target字段 //保存当前委托保存方法,要使用的实例
_methodPtr字段 //保存委托保存的方法
_invoalcationList字段 //保存委托链(如果只有一个委托就Null)
public class MyClass{ Public void Method1(int y){ } public static void Method2(int y){ } }
1、当我们使用MyDelegate del = new MyDelegate(new MyClass().Method1);
那么del对象中_target则保存了new MyClass()实例
_methodPtr保存了Method1地址
_invoalcationList此时为NULL,因为只有一个委托
当我们调用del(10),实际上是调用del.Invoke(10) 然后Invoke执行的是_target._methodPtr(10)
2、当我们使用MyDelegate del2 = new MyDelegate(MyClass.Method2);
那么del2对象中_target则保存了NULL,因为是保存静态方法,所以没有对象
_methodPtr保存了Method2地址
_invoalcationList此时为NULL,因为只有一个委托
当我们调用del2(10),实际上是调用del2.Invoke(10) 然后Invoke执行的是_target._methodPtr(10) 因为_target是null,所以实际是MyClass._methodPtr
3、del+=del2
那么实际是执行了del = Delegate.Combine(del,del2)
内部是创建了_invoalcationList数组,里面包含有两个委托del,del2
_target =null
_methodPtr =Method2地址
当我们调用del(10)时发现_invoalcationList里面有两个委托,则循环这个数组,分别调用每个委托