gpt4 book ai didi

c# - 为什么不能将 List 分配给 List

转载 作者:IT王子 更新时间:2023-10-29 04:28:44 26 4
gpt4 key购买 nike

我定义了以下类:

public abstract class AbstractPackageCall
{

...

}

我还定义了这个类的一个子类:

class PackageCall : AbstractPackageCall
{

...
}

AbstractPackageCall还有其他几个子类

现在我想进行以下调用:

 List<AbstractPackageCall> calls = package.getCalls();

但我总是得到这个异常(exception):

Error   13  Cannot implicitly convert type 'System.Collections.Generic.List<Prototype_Concept_2.model.PackageCall>' to 'System.Collections.Generic.List<Prototype_Concept_2.model.AbstractPackageCall>' 

这里有什么问题?这是方法 Package#getCalls

 internal List<PackageCall> getCalls()
{
return calls;
}

最佳答案

理解为什么不允许这样做的最简单方法是以下示例:

abstract class Fruit
{
}

class Apple : Fruit
{
}

class Banana : Fruit
{
}

// This should intuitively compile right? Cause an Apple is Fruit.
List<Fruit> fruits = new List<Apple>();

// But what if I do this? Adding a Banana to a list of Apples
fruits.Add(new Banana());

最后一条语句会破坏 .NET 的类型安全。

然而,数组确实允许这样做:

Fruit[] fruits = new Apple[10]; // This is perfectly fine

但是,将 Banana进入fruits仍然会破坏类型安全,因此 .NET 必须对每个数组插入进行类型检查,如果它实际上不是 Apple 则抛出异常.这可能是一个(小的)性能损失,但这可以通过创建 struct 来规避。包装这两种类型,因为这种检查不会发生在值类型上(因为它们不能继承任何东西)。起初,我不明白为什么做出这个决定,但你会经常遇到为什么这很有用。最常见的是 String.Format ,这需要 params object[]并且任何数组都可以传递给它。

但在 .NET 4 中,有类型安全的协变/逆变,它允许您进行一些类似的分配,但前提是它们可以证明是安全的。什么是可证明安全的?

IEnumerable<Fruit> fruits = new List<Apple>();

以上在 .NET 4 中有效,因为 IEnumerable<T>变成了IEnumerable<out T> . out意味着 T只能从 fruits出来并且在 IEnumerable<out T>根本没有方法曾经需要 T作为参数,所以你永远不会错误地传递 Banana 进入 IEnumerable<Fruit> .

逆变是一样的,但我总是忘记它的确切细节。毫不奇怪,现在有 in类型参数的关键字。

关于c# - 为什么不能将 List<Derived> 分配给 List<Base>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4652858/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com