1、当咱们使用关键字delegate声明一个自定义委托类型时,其实是声明了一个该名称的类类型,继承自抽象类System.MulticastDelegate,还包含实例方法Invoke、BeginInvoke、EndInvoke:异步
public delegate void MyDelegate();
其中的构造函数中第二个参数是native int类型的,这个是什么呢?咱们接着看:函数
咱们知道在C#中任何方法均可以直接赋值给签名一致的委托实例,这个过程看似并不合理,按理来讲C#中不支持直接获取函数的指针,其实这里是由编译器进行了取址操做,查看IL代码可知:spa
MyDelegate myDelegate = myObj.MyFunc;
能够看到由编译器为咱们进行了构建委托实例的过程,并且这里调用了ldftn命令将实例方法MyFunc()的native int类型的非托管指针推到栈中,从而将该方法的指针传到委托的构造函数中;线程
因为上面的构造函数存在C#中不支持的函数指针类型void(),因此不能在运行时使用Activator类中的方法建立委托实例,但在委托基类Delegate中存在静态方法CreateDelegate()调用非托管代码用于动态建立委托实例,命名空间System.Reflection中的方法信息类MethodInfo的实例方法CreateDelegate()也提供了相似的方式以在运行时动态构建委托实例:3d
Type delegateType = typeof(MyDelegate); //这里以可访问到的委托类型举例 Delegate @delegate = Delegate.CreateDelegate(delegateType, myObj, "MyFunc"); //@delegate = typeof(MyClass).GetMethod("MyFunc").CreateDelegate(delegateType, myObj); //添加其它委托实例 @delegate = Delegate.Combine(@delegate, otherDelegate); //调用委托 @delegate.DynamicInvoke(); //当指定的委托类型可访问时,能够将委托实例显式转换为指定的委托类型后使用()或Invoke()正常调用 //MyDelegate myDelegate = @delegate as MyDelegate; //myDelegate();
对委托实例或方法的+、+=操做实际上也是调用基类Delegate中的静态方法Combine()并将合成后的委托强制转换为原类型后返回,-、-=操做则是调用静态方法Remove();指针
2、委托的异步调用:经过委托类型的实例方法BeginInvoke开启子线程并在该子线程中执行委托实例中的方法,以此种方式调用的委托实例中有且只能有一个方法,若是包含多个方法,会抛出异常ArgumentException:code
myDelegate.BeginInvoke(null, null); //其中第一个参数为AsyncCallback类型的回调函数
若是须要异步调用一个委托实例中方法列表中的全部方法,须要先获取方法列表,再依次进行异步调用:blog
Delegate[] delegates = myDelegate.GetInvocationList(); for (int i = 0; i < delegates.Length; i++) { (delegates[i] as MyDelegate).BeginInvoke(null, null); }
3、当调用委托时,若是方法列表中某个方法内引起异常且未在该方法体内捕获时,该异常将传递给委托的调用方,而且再也不调用方法列表中的后面的方法,所以在方法体内捕获异常显得尤其重要;继承
4、泛型中的委托:自定义泛型委托(Generic Delegate),将类型参数用做参数列表或返回值的类型:get
delegate void MyDelegate<T>(T obj); //声明具备一个类型参数的泛型委托,参数列表中有一个参数 void MyGenericFunc<T>(T obj) //声明一个泛型方法,参数列表中有一个参数 { //do… } void MyFunc(string str) { //do… } //声明泛型委托的实例,指定类型参数为string类型,此时可匹配的方法签名为void myFunc(string str) MyDelegate<string> myDelegate; //赋值一个指定类型参数为string的泛型方法 myDelegate = MyGenericFunc<string>; //添加一个参数列表为string类型的具体方法 myDelegate += MyFunc;
※泛型委托同泛型类同样,须要在实例化时指定类型参数的类型;
※泛型委托的实例同具体委托的实例同样,只须要方法的参数列表和返回值类型相同便可进行匹配,所以无论目标方法是指定了符合要求类型的泛型方法仍是具体方法均可以进行匹配;
若是您以为阅读本文对您有帮助,请点一下“推荐”按钮,您的承认是我写做的最大动力!
做者:Minotauros
出处:https://www.cnblogs.com/minotauros/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。