Delegate委托

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

一、委托的定义、声明、实例化以及调用

1、我自己比较容易理解的定义

1、将方法当做参数传递,但类型是安全的。

2、声明、实例化、调用
1.带参数无返回值的委托
//声明一个带参数无返回值的委托
public delegate void DelegateNoReturn(int param);

//实例化一个委托
DelegateNoReturn dnr = new DelegateNoReturn(t =>
{
    Console.WriteLine(t);
});
复制代码
2.带参数带返回值的委托
public delegate int DelegateReturnAndParam(int param);
//实例化一个委托
DelegateReturnAndParam drap = new DelegateReturnAndParam(t =>
{
    return 1;
});
复制代码
3.带参数带返回值的委托
//声明一个无参数带返回值的委托
public delegate int DelegateNoParam();
//实例化一个委托
DelegateNoParam dnp = new DelegateNoParam(() =>
{
    return 1;
});

//调用
static void Main(string[] args)
{
    new Program().dnr(5);
    new Program().drap(5);
    new Program().dnp();
}
复制代码

二、泛型委托Action,Func

1、什么是泛型委托?

image.png

A: 最终就是一个基于Delagate和泛型结合的封装而已。

1:Action用于没有返回值的方法(参数可以根据自己情况进行传递)
2:Func用于有返回值的方法(同样参数视情况而定)
复制代码

三、委托的本质

1、委托是一个类
internal delegate void TestDelagate();
复制代码
1、编译器首先会定义一个完整的类并继承自MulticastDelegate类(所有的委托都派生自MulticastDelegate,
   MulticastDelegate派生自Delegate>Object,历史原因造成由2个委托类)。
2、类中由4个方法,分别是构造方法,Invoke、BeginInvoke、EndInvoke方法。
3、由于委托是类,所以凡是能够定义类的地方,都能定义委托。
复制代码
2、MulticastDelegate包含3个非公共的字段
1、_target为Object类型,当委托包装一个静态方法的时候这个值为null,当委托对象包装实例方法时这个字段引用
    回调方法要操作的对象(回调函数的作用域this)。
2、_MethodPtr为IntPtr类型,CLR利用它标识要回调的方法。
3、_invocationList为Object类型通常为null,构造委托链时它引用一个委托数组。
复制代码
3、每一个委托都有一个构造器
1、获取2个参数,一个对象引用,一个引用了回调方法的整数,对象的引用会被传给Object参数类型的_target。
2、另外一个回传给IntPtr参数类型的_MethodPtr,对于静态方法会将_target和_invocationList设置为null。
复制代码
4、结合上面放一个一目了然的小栗子
public class delegateTest
{
   public delegate void DelegateNoReturn(int param);
   //实例化一个委托传入静态方法
   DelegateNoReturn staticCallMethod = new DelegateNoReturn(delegateTest.staticMethod);
   //实例化一个委托传入实例方法
   DelegateNoReturn instanceCallMethod = new DelegateNoReturn(new delegateTest().instanceCallMethod);

   //静态函数
   public static void staticMethod(int Param){ }
   //实例方法
   public void instanceMethod(int Param) { }

}
复制代码

image.png

5、用委托回调多个方法(委托链了解一下)