泛型之逆变和协变总结

Posted 明明.如月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了泛型之逆变和协变总结相关的知识,希望对你有一定的参考价值。

泛型之逆变和协变总结

变的概念

  1. //父类 = 子类 
  2. string str = "string"
  3. object obj = str;//变了 

协变(Foo<父类> = Foo<子类> )

  1. //泛型委托: 
  2. public delegate T MyFuncA<T>();//不支持逆变与协变 
  3. public delegate T MyFuncB<out T>();//支持协变 
  4.  
  5. MyFuncA<object> funcAObject = null
  6. MyFuncA<string> funcAString = null
  7. MyFuncB<object> funcBObject = null
  8. MyFuncB<string> funcBString = null
  9.  
  10. funcAObject = funcAString;//编译失败,MyFuncA不支持逆变与协变 
  11. funcBObject = funcBString;//变了,协变 

逆变(Foo<子类> = Foo<父类>)

  1. public delegate void MyActionA<T>(T param);//不支持逆变与协变 
  2. public delegate void MyActionB<in T>(T param);//支持逆变 
  3.  
  4. MyActionA<object> actionAObject = null
  5. MyActionA<string> actionAString = null
  6. MyActionB<object> actionBObject = null
  7. MyActionB<string> actionBString = null
  8.  
  9. actionAString = actionAObject;//MyActionA不支持逆变与协变,编译失败 
  10. actionBString = actionBObject;//变了,逆变 
  11.  

在泛型参数上添加了in关键字作为泛型修饰符的话,那么那个泛型参数就只能用作方法的输入参数,或者只写属性的参数,不能作为方法返回值等,总之就是只能是“入”,不能出。out关键字反之。

逆变与协变的相互作用

  1. public interface IBar<in T> { } 
  2. //应该是in 
  3. public interface IFoo<in T

  4. void Test(IBar<T> bar)

  5. //还是out 
  6. public interface IFoo<out T

  7. void Test(IBar<T> bar)

有协变能力的IFoo要求它的泛型参数(IBar)有逆变能力

以上是关于泛型之逆变和协变总结的主要内容,如果未能解决你的问题,请参考以下文章

CLR 协变逆变

OOP中的逆变和协变

逆变和协变 in,out有关

逆变和协变 in,out有关

C#高级语法之泛型泛型约束,类型安全逆变和协变(思想原理)

Kotlin泛型 ③ ( 泛型 out 协变 | 泛型 in 逆变 | 泛型 invariant 不变 | 泛型逆变协变代码示例 | 使用 reified 关键字检查泛型参数类型 )