C#学习教程:为什么接口类型列表不能接受inheritance接口的实例?分享


为什么接口类型列表不能接受inheritance接口的实例?

给出以下类型:

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 list = new List(); 

这会导致以下编译错误:

参数类型’System.Collections.Generic.List’不能赋值参数类型’System.Collections.Generic.List’

我理解错误,我意识到有一些解决方法。 我只是没有看到任何明确的原因,为什么不允许这种直接转换。 毕竟, ISecondary列表中包含的值应该是(通过扩展名) IPrimary类型的值。为什么ListList被解释为不相关的类型?

任何人都可以清楚地解释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 {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 list){ } } 

为什么我不这样做? List list = new List();

想象一下,你有一个像这样定义的方法:

 public void PopulateList(List listToPopulate) { listToPopulate.Add(new Primary()); // Primary does not implement ISecondary! } 

如果您将List作为参数传递给它会发生什么?

List无法从List分配的错误是编译器让您摆脱这些麻烦的方法。

 public class Animal { ... } public class Cat: Animal { public void Meow(){...} } List cats = new List(); cats.Add(new Cat()); cats[0].Meow(); // Fine. List 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! 

这就是原因。

 class Evil : IPrimary {...} list.Add(new Evil()); // valid c#, but wouldn't work 

它可以保护您免受错误的影响。 列表实例(对象)需要辅助实例。 不是每个小学都是次要的。 然而,期望的是,主要名单可以容纳任何主要名单。 如果我们可以将二级列表视为主要列表:坏事。

实际上,数组确实允许这样 – 如果你弄错了,运行时会出错。

列表类型在其generics参数中不协变的原因,即List不是List的子类型,因为它们是读写的。 在您的扩展示例中,您的方法AcceptList可以执行list.Add(x) ,其中xIPrimary但不是ISecondary

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

上述就是C#学习教程:为什么接口类型列表不能接受inheritance接口的实例?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/1032007.html

发表评论

邮箱地址不会被公开。 必填项已用*标注