为什么通用的IList<>不继承非泛型的IList [英] Why generic IList<> does not inherit non-generic IList

查看:169
本文介绍了为什么通用的IList<>不继承非泛型的IList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的IList< T> 不继承的IList ,其中的IEnumerable<出T> 继承的IEnumerable

如果退出修正是唯一的原因,那么为什么大多数的IList&LT的执行情况; T> (如收藏< T> 名单,其中,T> )实现的IList 接口。

If out modifier are the only reason then why most of the implementation of IList<T> (e.g. Collection<T>, List<T>) implements IList interface.

因此​​,任何人能说好,如果这语句是适用于所有实施的IList&LT的; T&GT; 然后直接将其转换为的IList 在必要的时候。但问题是,虽然的IList&LT; T&GT; 不继承的IList ,因此不能保证每个的IList&LT; T&GT; 对象是的IList

So any one can say OK, if that statements is true for all implementation of IList<T> then directly cast it to IList when necessary. But problem is that though IList<T> does not inherit IList so it is not guaranteed that every IList<T> object are IList.

此外使用的IList&LT;对象&gt; 显然不是解决办法,因为没有退出修改仿制药不能分配到一个不太继承类;并创建目录的新实例是不是一个解决方案,在这里,因为有人可能希望的IList&LT的实际参考; T&GT; 的IList 指针;并使用名单,其中,T&GT; 的insteed 的IList&LT; T&GT; 实际上是一个不好的编程习惯,不服务于所有目的。

Moreover using IList<object> is obviously not the solution because without out modifier generics can not be assigned to a less inherit class; and creating new instance of List is not a solution here because someone may want actual reference of the IList<T> as an IList pointer; and use List<T> insteed of IList<T> is actually a bad programming practice and doesn't serve all purpose.

如果.NET想给灵活性,每个实施的IList&LT的; T&GT; 不应该有非一般的实现合同(即的IList ),那么他们为什么不保持它们实现通用和非通用版本,并没有表明其希望所有的具体类合同的通用和非遗传项通过,应该收缩的另一个接口接口。

If .NET wants to give flexibility that every implementation of IList<T> should not have a contract of non-generic implementation (i.e. IList) then why they didn't keep another interface which implement both generic and non-generic version and didn't suggest that all concrete class which want to contract for generic and non-genetic item should contract via that interface.

同样的问题出现铸造的ICollection&LT; T&GT; 的ICollection 的IDictionary&LT; TKEY的,TValue&GT; 的IDictionary

Same problem occurs for casting ICollection<T> to ICollection and IDictionary<TKey, TValue> to IDictionary.

推荐答案

正如您注意, T 的IList&LT; T&GT; 不是的的。作为一个经验法则:任何类可以修改它的状态不能协变的。其原因是这样的类通常具有有方法 T 作为自己的参数,例如中的一个的类型无效添加(T元素)。而协变型参数中不允许的输入的位置。

As you note, T in IList<T> is not covariant. As a rule of thumb: any class that can modify its state cannot be covariant. The reason is that such classes often have methods that have T as the type of one of their parameters, e.g. void Add(T element). And covariant type parameters are not allowed in input positions.

泛型增加了,除其他原因外,提供类型安全。例如,你不能添加苹果的列表。如果的ICollection&LT; T&GT; 要延长的ICollection ,那么你可以调用((ICollection的) myApples)。新增(someElephant)没有编译时错误,因为的ICollection 有一个方法无效添加(obj对象),它似乎允许您添加的任意的对象名单,而在实践中只能添加 T的对象。因此,的ICollection&LT; T&GT; 不延的ICollection 的IList&LT; T&GT; 不延的IList

Generics were added, among other reasons, to provide type safety. For example, you can't add an Elephant to a list of Apple. If ICollection<T> were to extend ICollection, then you could call ((ICollection)myApples).Add(someElephant) without a compile-time error, as ICollection has a method void Add(object obj), which seemingly allows you to add any object to the list, while in practice you can only add objects of T. Therefore, ICollection<T> does not extend ICollection and IList<T> does not extend IList.

安德斯·海尔斯伯格,C#的创造者之一,解释像这样

Anders Hejlsberg, one of the creators of C#, explains it like this:

在理想情况下所有的泛型集合接口(如ICollection的,IList的)会从他们的非通用同行继承,使得通用接口实例可以与通用和非通用code同时使用。

Ideally all of the generic collection interfaces (e.g. ICollection, IList) would inherit from their non-generic counterparts such that generic interface instances could be used both with generic and non-generic code.

事实证明,唯一的通用接口的量,这是可能的是IEnumerable的,因为只有IEnumerable的是禁忌的变体:在IEnumerable的,所述类型参数T仅用于输出的位置(返回值),而不是在输入位置(参数)。的ICollection和IList的使用T在输入和输出的位置,并且这些接口,因此不变。

As it turns out, the only generic interface for which this is possible is IEnumerable, because only IEnumerable is contra-variant: In IEnumerable, the type parameter T is used only in "output" positions (return values) and not in "input" positions (parameters). ICollection and IList use T in both input and output positions, and those interfaces are therefore invariant.

由于净4.5存在的 IReadOnlyCollection&LT;出T&GT; IReadOnlyList&LT;出T&GT; 协接口。但的IList&LT; T&GT; 的ICollection&LT; T&GT; 和许多列表和集合类不实行或延长他们。坦率地说,我觉得他们不是非常有用,因为它们只定义计数此[INT指数]


Since .Net 4.5 there are the IReadOnlyCollection<out T> and IReadOnlyList<out T> covariant interfaces. But IList<T>, ICollection<T> and many of the list and collection classes don't implement or extend them. Frankly, I find them not very useful, as they only define Count and this[int index].

如果我能重新设计的.Net 4.5,从地上爬了起来,我会分裂列表界面为只读协接口的IList&LT;出T&GT; ,包括包含的IndexOf ,和一个可变不变的接口 IMutableList&LT; T&GT; 。然后,你可以施放的IList&LT;苹果&GT; 的IList&LT;对象&gt; 。我实现了这个位置:

If I could redesign .Net 4.5 from the ground up, I would have split the list interface into a read-only covariant interface IList<out T> that includes Contains and IndexOf, and a mutable invariant interface IMutableList<T>. Then you could cast IList<Apple> to IList<object>. I implemented this here:

M42集合 - 协变的集合,列表和数组。

M42 Collections - Covariant collections, lists and arrays.

这篇关于为什么通用的IList&LT;&GT;不继承非泛型的IList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆