具有派生泛型类型的列表的奇怪行为
本文关键字:列表 派生 泛型类型 | 更新日期: 2023-09-27 18:06:43
所以我有一个基类型的列表。这个基类型有两个派生类,其中一个是泛型的。我试着逐一浏览列表,发现了这个奇怪的行为。
public static void Test<T>()
{
List<Base> myList = new List<Base>();
myList.Add(new aDerived());
myList.Add(new tDerived<T>());
foreach (tDerived<T> lGen in myList as List<tDerived<T>>)
{
// This is fine
}
foreach (aDerived lDerived in myList as List<aDerived>)
{
// Error: Can't convert... via a reference conversion etc
}
}
//Simple classes to repro:
class Base
{
}
class aDerived : Base
{
}
class tDerived<T> : Base
{
}
此报告错误CS0039如果指定了类型,即我将T替换为int而不是参数方法,那么我在第一个循环中也会得到相同的错误。
问题:为什么会这样?我看不出任何本质上不可能的事情,毕竟,我可以在每次迭代的返回类型上执行as
。另一方面,如果这个东西是模板类,为什么它能工作呢?这似乎不能帮助它工作。
以下操作均不能进行。不确定,但只要编译器知道aDerived
类型,它就会告诉您不能这样做(编译时错误)。但在第二种情况下,编译器没有足够的信息关于tDerived<T>
的确切类型(因为它将在运行时指定-因为你的方法是一个泛型方法),所以它不会通知你。但是当运行代码时,它会抛出异常。
var result1 = myList as List<aDerived>; //Compile-time error
var result2 = myList as List<tDerived<T>> //null
更有趣的:这可以在没有编译时错误的情况下完成:
List<Base> myList = new List<Base>();
var result = myList as List<T>; //No Compile-time error
这个链接也可能是有用的:协方差和逆变。
这个问题是您正在尝试将derived和tDerived的列表转换为其中一个或另一个。这是行不通的,因为它就像试图将水果列表(香蕉和苹果)转换成苹果列表一样。但是,您可以做的是使用OfType扩展来遍历正确类型的项:
foreach (tDerived<T> lGen in myList.OfType<tDerived<T>>())
{
Console.WriteLine("tDerived found!");
}
foreach (aDerived lDerived in myList.OfType<aDerived>())
{
Console.WriteLine("aDerived found!");
}
MSDN OfType: http://msdn.microsoft.com/en-us/library/bb360913(v=vs.100).aspx