C# 为什么可以';接口类型的列表是否接受继承接口的实例?

C# 为什么可以';接口类型的列表是否接受继承接口的实例?,c#,list,types,interface,C#,List,Types,Interface,鉴于以下类型: public interface IPrimary{ void doBattle(); } // an ISecondary "is" an IPrimary public interface ISecondary : IPrimary { } // An implementation of ISecondary is also an IPrimary: internal class SecondaryImpl : ISecondary { // Required,

鉴于以下类型:

public interface IPrimary{ void doBattle(); }

// an ISecondary "is" an IPrimary
public interface ISecondary : IPrimary {  }

// An implementation of ISecondary is also an IPrimary:
internal class SecondaryImpl : ISecondary
{
    // Required, since this is an IPrimary
    public void doBattle(){ }
}
为什么我不能这样做

List<IPrimary> list = new List<ISecondary>();
它是为了保护你不出错。列表实例(对象)需要辅助实例。并不是每一个小学都是中学。然而,人们的期望是,一个primary列表可以容纳任何primary。如果我们能把次要事物的清单当作主要事物的清单:坏东西

事实上,数组确实允许这样做,如果您弄错了,在运行时会出错

为什么我不能这样做<代码>列表=新列表()

假设您有一个定义如下的方法:

public void PopulateList(List<IPrimary> listToPopulate)
{
    listToPopulate.Add(new Primary());  // Primary does not implement ISecondary!
}
public void PopulateList(列表填充)
{
listToPopulate.Add(new Primary());//Primary未实现ISecondary!
}
如果将
列表作为参数传递给它,会发生什么


List
不能从
List
中赋值的错误是编译器帮助您摆脱这些麻烦的方法。

列表类型在其泛型参数中不协变的原因,即
List
不是
List
的子类型,是因为它们是读写的。在您的扩展示例中,您的方法
AcceptList
可以执行
list。添加(x)
,其中
x
i首要的
,而不是
i次要的

请注意,
IEnumerable
是正确的协变数组,而数组的类型是协变的(您可以尝试执行上面的操作),但出于同样的原因,这并不合理-向集合添加元素将在运行时失败。

公共类
public class Animal
{
    ...
}

public class Cat: Animal
{
    public void Meow(){...}
}

List<Cat> cats = new List<Cat>();

cats.Add(new Cat());

cats[0].Meow();  // Fine.

List<Animal> animals = cats; // Pretend this compiles.

animals.Add(new Animal()); // Also adds an Animal to the cats list, since animals references cats.

cats[1].Meow(); // cats[1] is an Animal, so this explodes!
{ ... } 公猫:动物 { 公共void Meow(){…} } 列表猫=新列表(); 添加(新的Cat()); 猫[0]。喵喵();//好的 列出动物=猫;//假设这是编译的。 动物。添加(新动物());//还将动物添加到猫列表中,因为动物引用猫。 猫[1]。喵喵();//猫[1]是一种动物,所以它爆炸了!

这就是为什么。

您想看看“C#中的泛型协方差”。和
List List=newlist()是没有意义的,即使你可以这么做。”@GrantThomas好的,可能有点简化;但是
someListOfTypePrimary.AddRange(someProvider.getListOftypeSecondary())呢?有什么原因不应该发生这种情况吗?我认为应该允许这样做,因为
AddRange
采用
IEnumerable
类型,它支持协方差-
IEnumerable
可以在任何地方使用
IEnumerable
。谢谢+一个富有洞察力和幽默感的例子。:)谢谢,很好的解释。请欣赏关于数组的旁注。
public void PopulateList(List<IPrimary> listToPopulate)
{
    listToPopulate.Add(new Primary());  // Primary does not implement ISecondary!
}
public class Animal
{
    ...
}

public class Cat: Animal
{
    public void Meow(){...}
}

List<Cat> cats = new List<Cat>();

cats.Add(new Cat());

cats[0].Meow();  // Fine.

List<Animal> animals = cats; // Pretend this compiles.

animals.Add(new Animal()); // Also adds an Animal to the cats list, since animals references cats.

cats[1].Meow(); // cats[1] is an Animal, so this explodes!