C# 4.0 为什么泛型类型参数的.NET4差异不适用于类?

C# 4.0 为什么泛型类型参数的.NET4差异不适用于类?,c#-4.0,covariance,contravariance,C# 4.0,Covariance,Contravariance,可能的重复项: 新的.NET 4.0泛型类型参数的协变和逆变仅适用于接口和委托。类不支持协方差的原因是什么?对于类型安全性,C#4.0仅对标有in或out的类型参数支持协方差/逆变 如果这扩展到类,您还必须用in-out标记类型参数,这将导致非常严格的限制。这很可能就是为什么CLR的设计者选择不允许它的原因。例如,考虑下面的类: public class Stack<T> { int position; T[] data = new T[100]; public vo

可能的重复项:

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

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

如果这扩展到类,您还必须用in-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[100];
public void Push(T obj){data[position++]=obj;}
public T Pop(){返回数据[--position];}
}
在我们的out中不可能将T注释为任意一个,因为T同时用于输入和输出位置。因此,这个类永远不能协变或逆变——即使在类的C#支持的协变/逆变类型参数中也是如此

接口很好地解决了这个问题。我们可以定义如下两个接口,并让堆栈实现这两个接口:

public interface IPoppable<out T> { T Pop(); }
public interface IPushable<in T> { void Push (T obj); }
公共接口ipopable{T Pop();}
公共接口IPushable{void Push(T obj);}
注意,T对于ipappable是协变的,对于IPushable是逆变的。这意味着T可以是协变的,也可以是逆变的,这取决于您是强制转换为iPappable还是IPushable


协方差/逆变换在类中使用有限的另一个原因是它将排除使用类型参数作为字段的可能性,因为字段实际上允许输入和输出操作。事实上,要编写一个用类型参数标记为In或out的类来做任何有用的事情是很困难的。即使是编写协变可枚举实现的最简单的情况也会带来一个挑战-如何从一开始就将源数据导入实例?

与C和VB.NET团队一起的.NET团队资源有限,他们在协变和逆变方面所做的工作解决了大部分现实问题。类型系统非常复杂,很难正确操作——如果在其他情况下导致不安全代码,那么在99.9999%的情况下有效的解决方案是不够好的

我认为在类方法上支持协方差和逆变规范(例如“in”/“out”)的成本/时间没有足够的价值。由于缺少多类继承,我几乎看不到它们可用的情况

您是否愿意为.net再等6个月以获得此支持?


另一种思考方法是在.net中

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

不确定您在这里谈论的是什么,类支持协方差和逆变:请看这篇博文:那篇文章只是为代表们展示了方差。谁投票以“不是真正的问题”作为结束?这是一个非常好的问题……是的!:)实际上,Stackoverflow完全是一个问题,人们试图将新的方差应用到类中(但自然失败)。@Thomas:是的,我有。变异不是黑魔法,这个概念几个世纪以来就被很好地理解了,并且已经被证明可以工作几十次了。事实上,有了方差和更好的编译器,就有可能在编译时检测到错误,这会导致以前在运行时未检测到的错误。因此,支持真实差异可以使程序更正确。NET方法与Java中的泛型方法是相同的借口;我很恼火的是,没有一个主流的虚拟机不采用“让我们一起动手”的方法来设计类型系统。一个类类型,它在构造函数中接受
t
类型的参数,但没有其他实例方法,并且有返回类型
t
的方法,理论上,在
T
中可以是协变的,没有任何类型的安全问题。困难来自于静态变量。如果类
Thing
具有类型为
int
的公共静态字段
Foo
Thing
将具有与
Thing
不同的
Foo