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

时间:2010-09-29 09:04:12

标签: c#-4.0 covariance contravariance

  

可能重复:
  Why isn't there generic variance for classes in C# 4.0?
  Why does C# (4.0) not allow co- and contravariance in generic class types?

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

2 个答案:

答案 0 :(得分:8)

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

如果扩展到类,你还必须在我们的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]; }
}

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

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

public interface IPoppable<out T> { T Pop(); }
public interface IPushable<in T> { void Push (T obj); }

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

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

答案 1 :(得分:1)

.NET团队以及C#和VB.NET团队的资源有限,他们在共同和逆变上所做的工作解决了大部分现实问题。类型系统非常复杂 - 如果在其他情况下导致不安全的代码,那么在99.9999%的情况下工作的解决方案就不够好。

我不认为在类方法上支持共同和逆变规范(例如“in”/“out”)的成本/时间具有足够大的价值。我可以看到极少数情况下它们是可用的 - 由于缺少乘法类继承。

您是否宁愿等待另外6个月的.net以获得此支持?


另一种想到这一点的方法是.net

  • 接口 / delegates - 用于为应用程序的概念类型系统建模
  • 用于实施上述类型
  • 类继承用于在执行上述操作时减少代码重复
  • 合作和逆转是关于应用的概念类型系统