为什么不能列出<parent> = List <child>?</child> </parent>

时间:2009-07-23 02:08:58

标签: c# .net oop inheritance

为什么以下代码不起作用?

class parent {}
class kid:parent {}

List<parent> parents=new List<kid>;

对我来说这似乎很明显。这是怎么回事?

5 个答案:

答案 0 :(得分:10)

C#目前不支持covariance

然而,在.NET 4.0中,它是coming在接口和委托上。

Eric Lippert在他的博客上有一段非常好的seriesVisual Studio Magazine在最近的article中也涵盖了这一点。

答案 1 :(得分:4)

除了在版本4.0之前的C#中缺少通用差异支持,List是可变的,因此不能安全地协变。考虑一下:

void AddOne<T>(List<T> arg) where T : new()
{
    arg.Add(new T());
}

void Whoops()
{
    List<parent> contradiction = new List<kid>();
    AddOne(contradiction);  // what should this do?
}

这会尝试将Parent添加到通过List引用引用的List,这是不安全的。允许数组由运行时协变,但在突变时进行类型检查,如果新元素不能分配给数组的运行时元素类型,则抛出异常。

答案 2 :(得分:2)

您正在寻找的功能称为协方差。在版本4.0之前的C#中不支持它,然后仅在接口和委托上支持它。

有关该主题的一些链接

答案 3 :(得分:1)

如果您知道List<Parent>包含List<child>,您可以使用扩展方法来“转换”,(实际上只需将父类型为子类型并将其返回列表中。例如像:

  public static List<T> Convert<T, T2>(this List<T2> input) {
      return input.OfType<T>().ToList();
    }

我不确定这对你有帮助,但我的价值2美分!我用的很多。

答案 4 :(得分:0)

正如已经指出的那样,C#目前不支持。在Java中,数组是协变的,它可能会导致一些问题。考虑一下你的例子,实际的列表应该是一个“kid”列表,这意味着它中的所有对象都应该是“kid”(或“孙子”)。但是,如果您用于访问列表的引用是“父”列表,那么您可以在列表中插入“父”,这显然不应该发生。