今天回忆了之前看的深入理解 C#这本书中的泛型章节, 其中对泛型的可变性的理解. 泛型可变性分两种: 协变和逆变. 逆变也又称为抗变.
怎么理解这两个名词的意思:
: 协变即为在泛型接口类型中使用 out 标识的类型参数. 协变的字面意思是 "与变化的方向相同"逆变那就是用 in 来标识的泛型接口类型的类型参数. 逆变的字面意思是 "与变化的方向相反"
需要注意的是无论是协变还是逆变也只能在泛型接口中来使用.
先来举个基本的例子, 来加强你对可变性的理解. 在 C# 中有隐式类型转换, 比如:
- string str = "nibian";
- object str1 = str;
- Console.WriteLine(str1);
大家都知道 string 类型是 object 类型的子类型, 即 string->object 为子 -> 父; 从子类型到父类型的转换是隐式类型转换.
举个例子:
- interface IDemo<out T>
- {
- T Method(string str);
- }
- class One : IDemo<string>
- {
- public string Method(string str)
- {
- return str;
- }
- }
- class Two : IDemo<object>
- {
- public object Method(string str)
- {
- return str;
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- IDemo<string> one = new One();
- IDemo<object> two;
- two = one;
- Console.WriteLine(two.Method("2222"));
- }
- }
因为 string 是 object 类型的子类, 在这里 IDemo<string > 和 IDemo<object > 类型之间也存在着类型转换的, 从 IDemo<string > 向 IDemo<object > 进行的转换可以看成是子类型向父类型的隐式转换, 它的这个用法就是协变.(这里必须要用 out)
相反的我们在来看一下有关逆变的代码:
- interface IDemo<in T>
- {
- string Method(T str);
- }
- class One : IDemo<string>
- {
- public string Method(string str)
- {
- return str;
- }
- }
- class Two : IDemo<object>
- {
- public string Method(object str)
- {
- return str.ToString();
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- IDemo<object> two = new Two();
- IDemo<string> one;
- one = two;
- Console.WriteLine(one.Method("2222"));
- }
- }
同样的从 IDemo<object > 类型向 IDemo<string > 类型的转换, 但是在这里我们却将父类型隐式转换为子类型的用法叫逆变.(这里必须要用 in)
总结: 协变和逆变就是在泛型接口类型将类型参数作为输入和输出的情况下, 对类型间进行隐式转换的规律.
来源: https://www.cnblogs.com/yubabuneng/p/9506037.html