.NET 泛型中的协变和逆变

协变(Covariance)

使你能够使用比原始指定的类型派生程度更大的类型。

你可以将 IEnumerable<Derived> 的实例分配给 IEnumerable<Base> 类型的变量。

简单理解:把细的赋给粗的,适用于赋值

示例

public class Base
{
}

public class Derived : Base
{
}

IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;

可以看出,很像多态嘛。

以上在 .NET Framework 3.5 中是报错的,但是在 4.6.2,它不会报错。

逆变(Contravariance)

使你能够使用比原始指定的类型更泛型(派生程度更小)的类型。

你可以将 Action<Base> 的实例分配给 Action<Derived> 类型的变量。

简单理解:把粗的赋给细的,适用于赋形参

// 如下是不行的。
IEnumerable<Base> d = new List<Base>();
IEnumerable<Derived> b = d; // 这里会报错。

// 但是作为参数是可以的。
Action<Base> b = (p) => { };
Action<Derived> d = b; // 正常。

之所有可以把粗的赋给细的,是因为这是形参,不是实在的对象。

有什么用?

除了理解编程原理,意义真不大,如果意义大,经常用到,大家就很熟悉了。

Action<Base> b = (p) => { };
Action<Derived> d = b;

b(new Derived());
b(new Base());

d(new Derived());
d(new Base()); // 错误。

如上代码 b 这个方法,传 Derived、Base 对象都可以,但是我某处应用就不希望传 Base 对象,于是 Action<Derived> d = b;(逆变),d 就不能用 Base 对象了。

相关阅读

  • 泛型中的协变和逆变 | Microsoft Docs

  • C# 中 Action 和 Func

你可能感兴趣的