为什么泛型类型参数的.NET 4方差也不适用于类?

bit*_*onk 3 covariance contravariance c#-4.0

可能重复:
为什么C#4.0中的类没有通用方差?
为什么C#(4.0)不允许泛型类的共同和逆变?

新的.NET 4.0泛型类型参数的协同和逆变仅适用于接口和委托.不支持课程的原因是什么?

Joe*_*ari 8

对于类型安全,C#4.0仅支持用inout标记的类型参数的协方差/逆变.

如果这扩展到类,你还必须在我们的out中标记类型参数,这将最终是非常严格的.这很可能是CLR的设计者选择不允许的原因.例如,考虑以下类:

public class Stack<T>
{
  int position;
  T[] data = new T[100];
  public void Push (T obj)   { data[position++] = obj;  }
  public T Pop()             { return data[--position]; }
}
Run Code Online (Sandbox Code Playgroud)

在我们的输出中也不可能注释T,因为T用于输入和输出位置.因此,这个类永远不会协变或逆变 - 即使在C#支持的类的协方差/逆变类型参数中也是如此.

接口很好地解决了这个问题.我们可以按如下方式定义两个接口,并使用Stack实现两者:

public interface IPoppable<out T> { T Pop(); }
public interface IPushable<in T> { void Push (T obj); }
Run Code Online (Sandbox Code Playgroud)

注意,对于IPusable,T是协变的,对于IPushable,T是逆变的.这意味着T可以是协变的或逆变的 - 取决于你是否转换为IPoppable或IPushable.

协方差/逆变法对类的使用有限的另一个原因是它会排除使用类型参数作为字段 - 因为字段有效地允许输入和输出操作.实际上,编写一个对标记为in或out的类型参数完全有用的类是很困难的.即使是编写协变Enumerable实现的最简单的情况也会带来挑战 - 如何将源数据引入实例开始?