将List<DerivedClass>转换为List<BaseClass>

247

虽然我们可以继承基类/接口,但为什么不能使用相同的类/接口声明一个List<>

interface A
{ }

class B : A
{ }

class C : B
{ }

class Test
{
    static void Main(string[] args)
    {
        A a = new C(); // OK
        List<A> listOfA = new List<C>(); // compiler Error
    }
}

有什么绕过的方法吗?


1
https://dev59.com/VWQn5IYBdhLWcg3wRVVs - cuongle
13个回答

0

我已经阅读了整个主题,我只想指出一个似乎对我来说不一致的地方。

编译器会阻止您使用列表进行赋值:

List<Tiger> myTigersList = new List<Tiger>() { new Tiger(), new Tiger(), new Tiger() };
List<Animal> myAnimalsList = myTigersList;    // Compiler error

但编译器对于数组是完全没有问题的:

Tiger[] myTigersArray = new Tiger[3] { new Tiger(), new Tiger(), new Tiger() };
Animal[] myAnimalsArray = myTigersArray;    // No problem

关于赋值是否“已知安全”的争论在这里破裂了。我对数组进行的赋值“不安全”。为了证明这一点,如果我接下来这样做:

myAnimalsArray[1] = new Giraffe();

我收到一个运行时异常"ArrayTypeMismatchException"。这是怎么回事?如果编译器真的想防止我做一些愚蠢的事情,它应该阻止我执行数组赋值。


0

您也可以使用 System.Runtime.CompilerServices.Unsafe NuGet 包来创建对同一个 List 的引用:

using System.Runtime.CompilerServices;
...
class Tool { }
class Hammer : Tool { }
...
var hammers = new List<Hammer>();
...
var tools = Unsafe.As<List<Tool>>(hammers);

根据上面的示例,您可以使用tools变量访问列表中现有的Hammer实例。将Tool实例添加到列表中会抛出ArrayTypeMismatchException异常,因为tools引用与hammers相同的变量。


0

因为C#目前不允许那种类型的继承转换(链接)


6
首先,这是一个可转换性问题,而不是继承性问题。其次,泛型类型的协变在类类型上无法工作,只能在接口和委托类型上使用。 - Eric Lippert
5
好的,我不太能够反驳你。 - Noon Silk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接