C#Casting Generic Type
我有一个通用接口IConstrained,由通用的Constrained类实现。 当我尝试执行下面的代码时,我得到一个无效的强制转换exception。
IConstrained decimalLimit = new Constrained(1); IConstrained comparableLimit = (IConstrained) decimalLimit;
如果十进制实现IComparable,为什么不能这样做呢? 这样做的正确方法是什么? 谢谢。
.NET 2.0中的generics类型不协变。 这包括.NET 3.0 / 3.5,因为它们使用相同的2.0运行时。 但是,.NET 4.0将支持协方差 。
将IConstrained
Erik Lippert有一系列博客文章,详细介绍了Contravariance和Covariance 。
为了解决这个问题,你必须在使用它时将十进制数转换为IComparable。
这是与C#(以及generics的其他语言)共同的旅行。
在C#中,只能转换为类层次结构中的类(超类,子类)。 但IConstrained
既不是超类,也不是IConstrained
的子类,即使decimal实现了IComparable。 C#不允许这样做的原因是因为允许它意味着你可以做很糟糕的事情。
有关其原因的详细说明,请查看此类似问题
对于像这样可IConstrained
的类,它需要实现两个接口IConstrained
class A:IConstrained,IConstrained
它不会自动发生,因为.NET 2.0不实现协方差或逆变。 IConstrained
不实现IConstrained
。 是的,这是令人沮丧和反直觉的。 根据我的理解,在C#4.0中实际上会以这种或那种forms支持这种情况。 它被称为协方差或逆变。
编辑:我对Constrained类并不熟悉,但你可以构造一个新的Contrained
并传递给它一个小数。 如果它有一个Constrained
forms的构造函数,那么你可以声明一个新的Constrained
并将小数传递给它。 有点像制作副本。
编辑2:在此页面的大约一半处,搜索“2.0”,有一个如何在.NET 2.0中解决此问题的示例: http : //blog.tlk.com/dot-net/2009/c-尖锐-4-协方差和-逆变
这是“怎么做”的答案。
IList decimalLimit = new List (1); IEnumerable asComparable = decimalLimit.Cast (); IList comparableLimit = asComparable.ToList();
对于generics,具有不同类型参数的相同generics类型的两个实例彼此没有直接关系。 换一种说法:
IConstrained !== IConstrained
这是一个方差问题。 即使十进制是IComparable,IConstrained
阅读反方差和协方差。 意识到C#generics是不变的,你所要求的并不是你想要的。