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仅对标有in或out的类型参数支持协方差/逆变 如果这扩展到类,您还必须用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–用于为应用程序的概念类型系统建模
- 类用于实现上述类型
- 类继承用于在执行上述操作时减少代码重复
- 协变和逆变是关于应用程序的概念类型系统
t
类型的参数,但没有其他实例方法,并且有返回类型t
的方法,理论上,在T
中可以是协变的,没有任何类型的安全问题。困难来自于静态变量。如果类Thing
具有类型为int
的公共静态字段Foo
,Thing
将具有与Thing
不同的Foo
。