C#类型转换错误,尽管通用约束
-
06-07-2019 - |
题
为什么,对于类别参数T的<!>的类型参数T的通用约束必须从A <!>继承;第一次调用成功但第二次调用失败,并且类型转换错误在评价:
abstract class A { }
static class S
{
public static void DoFirst(A argument) { }
public static void DoSecond(ICollection<A> argument) { }
}
static class P<T>
where T : A, new()
{
static void Do()
{
S.DoFirst(new T()); // this call is OK
S.DoSecond(new List<T>()); // this call won't compile with:
/* cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.ICollection<A>' */
}
}
通用约束不应该确保List<T>
确实ICollection<A>
吗?
解决方案
这是C#缺乏关于泛型类型的协方差的一个例子(C# 支持数组协方差)。 C#4将在接口类型上添加此功能,并且还将更新多个BCL接口类型以支持它。
请参阅 C#4.0:协方差和逆变:
在这篇文章中我<!>#8217;试着覆盖一个 C#4.0创新。其中一个 新功能是协方差和 类型参数的逆变 现在由通用代表支持 和通用接口。首先让<!>#8217; s 看看这些词是什么意思:)
其他提示
约束对问题没有影响;问题是你在一个需要ICollection的参数中传递List - C#不支持协方差,所以你需要显式地将列表转换为ICollection:
S.DoSecond((ICollection<A>) new List<T>()); // this call will be happy
您已强烈输入DoSecond参数作为类型ICollection <!> lt; A <!> gt;。尽管T是A类型的事实,但在编译时,List <!> lt; T <!> gt;之间没有隐式强制转换。和ICollection <!> lt; A <!> gt;。您将需要创建列表并将其强制转换为ICollection <!> lt; A <!> gt;当你调用DoSecond时,或者让DoSecond本身成为通用方法。
注意:C#4.0应该支持这种类型的隐式强制转换,这将提供比C#3.0提供的更好的协变性。
不隶属于 StackOverflow