我有一个Circle对象数组(Circle实现了IShape接口,我有一个参数为List<IShape>
的函数。为什么我不能将我的Circles数组传递给它?
Visual Studio给出了一个构建错误,指出无法将List<Circle>
转换为List<IShape>
答案 0 :(得分:5)
简短的回答是因为函数Foo
可以像这样实现:
void Foo(IList<IShape> c)
{
c.Add(new Square());
}
如果您将List<Circle>
传递给Foo
,则提供的类型将无法存储Square
,即使类型签名声称它没有问题。 IList<T>
不是covariant:一般IList<Circle>
不能是IList<IShape>
,因为它不支持添加任意形状。
修复方法是使用IEnumerable<IShape>
接受Foo
中的参数,但这并不适用于所有情况。 IEnumerable<T>
是协变的:专门的IEnumerable<Circle>
符合一般IEnumerable<IShape>
的合同。
这种行为也是一件好事。不应该是协变的东西的典型例子是数组。以下代码将编译,但在运行时将失败:
void Bar()
{
// legal in C#:
object[] o = new string[10];
// fails with ArrayTypeMismatchException: can't store Int in a String[]
o[0] = 10;
}