委托
是一种定义方法签名的类型.
提供了回调函数机制,而且是类型安全的.
使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,提高了程序的可扩展性。
1. 声明 delegate
internal delegate void StudyTester(string arg);
在编译器中会生成 一个 namespace.StudyTester的类,其中包含 .ctor(构造函数),Invoke(回调方法),BeginInvoke,EndInvoke(异步回调方法).
所有的委托都会自动继承类System.MulticastDelegate。 MulticastDelegate又继承自Delegate。
2、实例化
StudyTester test= new StudyTester(param);
IL_0002: ldftn void namespace.Program::param(string)//将param的函数指针(非托管指针 native int 类型)推送到计算堆栈上
IL_0008: newobj instance void namespace.StudyTester::.ctor(object, native int) //创建一个新对象,并将对象引用推送到计算堆栈上
编译器在执行委托的构造时,会分析引用的对象,哪个方法,并将对象引用传递给object,param的函数指针传递给 native int
3.调用回调方法
test("chaoa") <=> test.Invoke("chaoa");
IL_0014: callvirt instance void namespace.StudyTester::Invoke(string) //对对象调用后期绑定方法,并且将返回值推送到计算堆栈上
Invoke使用了Win32API的SendMessage,
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
BeginInvoke使用了Win32API的PostMessage
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
4.Delegate 公共属性
Target:返回_target值 即获取类实例,当前委托调用其实例方法。
Method:获取委托所表示的方法.
5. 委托链 (是委托对象的集合,可以调用委托的所有方法)
委托链在构造时,使用了:
* Delegate.Combine(d1,d2);将委托添加到委托链中,若_invocationList不为空 则遍历数组 按顺序调用
* Delegate.Remove(d1,d2); 从d1的委托数组中查找与d2匹配的委托,匹配后删除.
+= 使用了运算符重载,它实际调用的是Delegate的Combine,-= 号实际调用的是Delegate的Remove