什么是委托

委托是一个对象,它知道如何调用一个方法

实例方法目标和静态方法目标

当一个实例方法被赋值给委托对象的时候,这个委托对象不仅要保留着对方法的引用,还要保留着方法所属实例的引用
System.Delegate的Target属性就代表着这个实例
如果引用的是静态方法,那么Target属性的值就是null
未命名图片.png

泛型委托类型

委托类型可以包含泛型类型参数

  1. public delegate T Transformer<T>(T arg);

未命名图片.png

Func和Action委托

使用泛型委托,就可以写出这样一组委托类型,他们可调用的方法可以拥有任意的返回类型和任意(合理)数量的参数。
在System命名空间下(意味着随时使用)
未命名图片.png
Func是有返回类型的委托,它的参数从0个到16个,从两个参数开始,前面的参数是in修饰(也就是逆变,可以作为输入),最后的一个参数是out修饰(协变,可以作为输出)
Action是没有返回类型的委托,它的参数也是从0个到16个,每个参数都是in修饰(逆变,只能作为输入)
上个例子用Func委托
未命名图片.png

委托 vs 接口

委托可以解决的问题,接口都可以解决

什么情况下更适合使用委托而不是接口呢?当下列条件之一满足是:
接口只能定义一个方法
需要多播能力
订阅者需要多次实现接口
未命名图片.png

委托的兼容性 - 委托类型

委托类型之间互不相容,即使方法签名一样

  1. delegate void D1();
  2. delegate void D2();
  3. D1 d1 = Method1;
  4. D2 d2 = d1; // 编译时错误!

委托的兼容性 - 委托类型

如果委托实例拥有相同的方法目标,那么委托实例就认为是相等的。

  1. delegate void D();
  2. ..
  3. D d1 = Method1;
  4. D d2 = Method1;
  5. Console.WriteLine(d1 == d2);
  6. //True

委托的兼容性 - 参数

当你调用一个方法时,你提供的参数(argument)可以比方法的参数(parameter)定义更具体。
委托可以接受比它的方法目标更具体的参数类型,这个叫ContraVariance(委托里面的逆变)。
未命名图片.png
和泛型类型参数一样,委托的variance仅支持引用转换。
未命名图片.png

委托的兼容性 - 返回类型

调用方法时,你可以得到一个比请求的类型更具体的类型的返回结果。
委托的目标方法可以返回比委托描述里更具体的类型的返回结果,Covariance.
未命名图片.png

泛型委托类型参数的variance

  1. Covarianceout (协变,只作为输出)
  2. ContraVariancein (逆变,只作为输入)