为什么.Net 4不允许我传入一个接口数组?

时间:2013-03-22 02:41:46

标签: c# collections covariance

我有一个Circle对象数组(Circle实现了IShape接口,我有一个参数为List<IShape>的函数。为什么我不能将我的Circles数组传递给它?

Visual Studio给出了一个构建错误,指出无法将List<Circle>转换为List<IShape>

1 个答案:

答案 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;
}