问题描述
我大致了解接口、继承和多态,但有一件事让我感到困惑.
I generally understand interfaces, inheritance and polymorphism, but one thing has me puzzled.
在这个例子中,Cat 实现了 IAnimal,当然 List 实现了 IList:
In this example, Cat implements IAnimal and of course List implements IList:
IList<IAnimal> cats = new List<Cat>();
但它会产生编译错误(无法隐式转换类型...).如果我使用 Cat 继承的抽象超类 [Animal],它也将不起作用.但是,如果我将 IAnimal 替换为 Cat:
but it generates a compilation error (Cannot implicitly convert type...). It also won't work if I use an asbtract superclass [Animal] that Cat inherits from. However, If I replace IAnimal with Cat:
IList<Cat> cats = new List<Cat>();
它编译得很好.
在我看来,因为 Cat 实现了 IAnimal,所以第一个示例应该是可以接受的,允许我们为两个列表返回一个接口和包含的类型.
In my mind, because Cat implements IAnimal, the first example should be acceptable, allowing us to return an interface for both the list and the contained type.
谁能解释为什么它无效?我确信有一个合乎逻辑的解释.
Can anyone explain why it isn't valid? I'm sure there's a logical explanation.
推荐答案
有一个合乎逻辑的解释,这个确切的问题几乎每天都在 StackOverflow 上被问到.
There is a logical explanation, and this exact question is asked pretty much every day on StackOverflow.
假设这是合法的:
IList<IAnimal> cats = new List<Cat>();
是什么阻止了这合法化?
What stops this from being legal?
cats.Add(new Giraffe());
什么都没有."cats" 是动物列表,而长颈鹿是动物,因此您可以将长颈鹿添加到猫列表中.
Nothing. "cats" is a list of animals, and a giraffe is an animal, and therefore you can add a giraffe to a list of cats.
显然这不是类型安全的.
Clearly that is not typesafe.
在 C# 4 中,我们添加了一项功能,如果元数据注释允许编译器证明它是类型安全的,您就可以这样做.在 C# 4 中,您可以这样做:
In C# 4 we added a feature whereby you can do that if the metadata annotations allow the compiler to prove that it is typesafe. In C# 4 you can do this:
IEnumerable<IAnimal> cats = new List<Cat>();
因为 IEnumerable<IAnimal>
没有 Add 方法,所以没有办法违反类型安全.
because IEnumerable<IAnimal>
has no Add method, so there is no way to violate type safety.
有关更多详细信息,请参阅我关于我们如何在 C# 4 中设计此功能的系列文章.
See my series of articles on how we designed this feature in C# 4 for more details.
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/default.aspx
(从底部开始.)
这篇关于IList<T>并列出<T>接口转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!