2

所以我有一个基本类型的列表。这个基类型有两个派生类,其中一个是泛型​​的。我试图遍历列表并发现了这种奇怪的行为。

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对每次迭代的返回类型进行操作。另一方面,如果事物是​​模板类,为什么它会起作用,似乎这不应该帮助它起作用。

4

2 回答 2

2

以下操作均不能进行。不确定,但只要编译器知道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

此链接也可能有用:Covariance and Contravariance

于 2013-03-30T19:22:56.023 回答
1

This issue is you are trying to convert a list of aDerived and tDerived into one or the other. This wont work as its like trying to convert a list of fruit (bananas and apples) into a list of apples. What you can do however is use the OfType extension to iterate over the items of the correct type:

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

于 2013-03-30T19:35:26.857 回答