为什么通用的IList&LT;&GT;不继承非泛型的IList [英] Why generic IList<> does not inherit non-generic IList
问题描述
的IList&LT; T&GT;
不继承的IList
,其中的IEnumerable&LT;出T&GT;
继承的IEnumerable
。
如果退出
修正是唯一的原因,那么为什么大多数的IList&LT的执行情况; T&GT;
(如收藏&LT; T&GT;
,名单,其中,T&GT;
)实现的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屋!