c# - 为什么接口(interface)类型的列表不能接受继承接口(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, since this is an IPrimary
    public void doBattle(){ }
}

为什么我不能这样做?

List<IPrimary> list = new List<ISecondary>();

这会导致以下编译错误:

Argument type 'System.Collections.Generic.List' is not assignable to parameter type 'System.Collections.Generic.List'

我了解错误,并且知道有解决方法。我只是看不出有任何明确的理由禁止这种直接转换。 ISecondary 列表中包含的值,毕竟应该是(通过扩展)IPrimary 类型的值.为什么然后是List<IPrimary>List<ISecondary>被解释为不相关的类型?

谁能解释清楚为什么 C# 会这样设计?

一个稍微扩展的例子:我在尝试做类似以下的事情时遇到了这个问题:

internal class Program
{
    private static void Main(string[] args)
    {
        // Instance of ISecondary, and by extention, IPrimary:
        var mySecondaryInstance = new SecondaryImpl();

        // This works as expected:
        AcceptImpl(mySecondaryInstance);

        // List of instances of ISecondary, which are also, 
        // by extention, instances of IPrimary:
        var myListOfSecondaries = new List<ISecondary> {mySecondaryInstance};

        // This, however, does not work (results in a compilation error):
        AcceptList(myListOfSecondaries);
    }

    // Note: IPrimary parameter:
    public static void AcceptImpl(IPrimary instance){  }

    // Note: List of type IPrimary:
    public static void AcceptList(List<IPrimary> list){  }

}

最佳答案

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!

这就是原因。

关于c# - 为什么接口(interface)类型的列表不能接受继承接口(interface)的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14621564/

相关文章:

c# - 如何将 SQL ELMAH_Error.ErrorID 附加到 ELMAH 错误电子邮件主题?

c# - 如何在复杂数据类型上做表达式树

c# - 从字符串数组中删除所有空元素

java列表通过重新排列链接来移动项目

arrays - 向下转换数组长度和索引

c# - 如何限制 foreach 循环中迭代的元素数量?

c# - 拆分字符串数组

python - 在列表中的列表之间找到减法的最大绝对值

types - Ocaml 抽象类型和类型推断

python - 如何在 Python 中正确检查对象类型?