.Net逆变与协变
总结:
- 协变与逆变只针对引用类型
- 协变:把子类型 赋值给 父类型,string 赋值给object叫‘类型兼容’,string[]赋值给object[] 叫协变
- 逆变:把父类型 赋值给 子类型,且不需要强制转换进行赋值,已经帮我们进行了隐式转换
1、接口中
- 协变式(泛型前加 out),只能用于方法的返回值
- 逆变式(泛型前加 in),只能用于方法的参数签名
首先来看一下接口的例子:
1 /// <summary> 2 /// 接口 3 /// </summary> 4 /// <typeparam name="Tin">Tin为逆变式,只能用于接口中函数的参数签名</typeparam> 5 /// <typeparam name="Tout">Tout为协变式,只能用于接口中函数的返回值类型</typeparam> 6 public interface Face<in Tin, out Tout> 7 { 8 //Tin Fun(double instance);错误的函数定义,编译就会报错 9 double Fun(Tin instance); 10 11 Tout Fun(double instance); 12 //double Fun(Tout instance);错误的函数定义,编译就会报错 13 }
2、在委托中:
- 不能将函数参数定义成协变,也不能将返回类型定义成逆变
1 /// <summary> 2 /// 委托 3 /// </summary> 4 /// <typeparam name="Tin">Tin为逆变式,只能用于委托中函数的参数签名</typeparam> 5 /// <typeparam name="Tout">Tout为协变式,只能用于委托中函数的返回值类型</typeparam> 6 /// <param name="instance"></param> 7 /// <returns></returns> 8 public delegate Tout MyDel<in Tin, out Tout>(Tin instance); 9 //public delegate Tin MyDel1<in Tin, out Tout>(Tout instance);错误的委托定义
下面来看看Action委托
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //以下能将Action<object>的实例赋值给Action<string>实例的原因就是由于Action委托是一个逆变式 6 Action<object> acObj = ActionFuncObj; 7 Action<string> acStr = acObj;
8 //以下表达式是错误的,因为Action是一个逆变式,所以无法将Action<string>实例赋值给Action<object>实例 9 //Action<string> acStr2 = ActionFuncStr; 10 //Action<object> acObj2 = acStr2; 11 } 12 static void ActionFuncStr(string str) 13 { 14 Console.WriteLine(str); 15 } 16 static void ActionFuncObj(object obj) 17 { 18 Console.WriteLine(obj); 19 } 20 }
下面来看看Func委托
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //以下能将Func<string, object>的实例赋值给Func<string, object>实例的原因就是由于Func委托是一个协变式 6 Func<string, string> funcStr = FuncStr; 7 Func<string, object> funcObj = funcStr; 8 9 //以下表达式是错误的,因为Func是一个协变式,所以无法将Func<string, object>实例赋值给Func<string, string>实例 10 //Func<string, string> funcStr2 = funcObj; 11 } 12 static string FuncStr(string str) 13 { 14 return str; 15 } 16 }

浙公网安备 33010602011771号