什么是委托
实例方法目标和静态方法目标
当一个实例方法被赋值给委托对象的时候,这个委托对象不仅要保留着对方法的引用,还要保留着方法所属实例的引用
System.Delegate的Target属性就代表着这个实例
如果引用的是静态方法,那么Target属性的值就是null
泛型委托类型
委托类型可以包含泛型类型参数
public delegate T Transformer<T>(T arg);
Func和Action委托
使用泛型委托,就可以写出这样一组委托类型,他们可调用的方法可以拥有任意的返回类型和任意(合理)数量的参数。
在System命名空间下(意味着随时使用)
Func是有返回类型的委托,它的参数从0个到16个,从两个参数开始,前面的参数是in修饰(也就是逆变,可以作为输入),最后的一个参数是out修饰(协变,可以作为输出)
Action是没有返回类型的委托,它的参数也是从0个到16个,每个参数都是in修饰(逆变,只能作为输入)
上个例子用Func委托
委托 vs 接口
委托可以解决的问题,接口都可以解决
什么情况下更适合使用委托而不是接口呢?当下列条件之一满足是:
接口只能定义一个方法
需要多播能力
订阅者需要多次实现接口
委托的兼容性 - 委托类型
委托类型之间互不相容,即使方法签名一样
delegate void D1();
delegate void D2();
D1 d1 = Method1;
D2 d2 = d1; // 编译时错误!
委托的兼容性 - 委托类型
如果委托实例拥有相同的方法目标,那么委托实例就认为是相等的。
delegate void D();
..
D d1 = Method1;
D d2 = Method1;
Console.WriteLine(d1 == d2);
//True
委托的兼容性 - 参数
当你调用一个方法时,你提供的参数(argument)可以比方法的参数(parameter)定义更具体。
委托可以接受比它的方法目标更具体的参数类型,这个叫ContraVariance(委托里面的逆变)。
和泛型类型参数一样,委托的variance仅支持引用转换。
委托的兼容性 - 返回类型
调用方法时,你可以得到一个比请求的类型更具体的类型的返回结果。
委托的目标方法可以返回比委托描述里更具体的类型的返回结果,Covariance.
泛型委托类型参数的variance
Covariance,out (协变,只作为输出)
ContraVariance,in (逆变,只作为输入)