为什么微软没有让ReadOnlyCollection<T>继承自ReadOnlyCollectionBase?

11
简单来说,微软定义了一个 ReadOnlyCollectionBase,但在 ReadOnlyCollection<T> 中并没有将其用作基类,尽管这听起来明显应该是这样的。

我有什么遗漏吗?我的意思是,有好的理由将这个类作为基类吗?

4个回答

21
可能是因为它不是泛型的,实现了ICollection,而ReadOnlyCollection<T>是泛型的,并实现了ICollection<T>。请注意,ICollection<T>并不实现ICollection。在这个主题上:

ICollection<T>看起来像是ICollection,但它实际上是一个非常不同的抽象。我们发现ICollection并不是很有用。同时,我们没有一种表示读/写非索引集合的抽象。 ICollection<T>就是这样的抽象,你可以说ICollection在泛型世界中没有确切相应的对等项;IEnumerable<T>是最接近的。

来自同一篇文章:

ReadOnlyCollection<T>是一个更好的ReadOnlyCollectionBase。它位于System.Collections.ObjectModel命名空间中。

从效果上讲,ReadOnlyCollection<T>是泛型空间中的ReadOnlyCollectionBase

同样地,请注意,IList<T>也不实现IList

总的来说,早期的非泛型类对于泛型类并不是有用的抽象(除了IEnumerable的例外)。


实际上,IEnumerable 在原则上和 IList 有相同的问题,但是相比于你需要为 IList 编写的几十个方法(List<T>ReadOnlyCollection<T> 都实现了这些方法,与泛型集合接口分开实现),实现一个额外的方法(以及在枚举器上增加一个额外的属性)并不被认为是负担。 - Random832
有没有想过为什么 IList<T> 没有继承自 ICollection?因为后者基本上是 IEnumerable 加上 Count,而且 IList<T> 已经有了一个 Count 方法,让 IList<T> 继承 ICollection 不需要实现者做更多的工作,但这样做可以让拥有 IList<anything> 的人知道从枚举中可以期望多少项。 - supercat

5
如果你查看 .net framework 的历史,你会发现自 2.0 版本以来就有泛型,但是在 1.1 版本中已经有了 ReadOnlyCollectionBase。没有选择 ReadOnlyCollectionBase 的原因很简单——它不是泛型,而 ReadOnlyCollection<T> 的目的是要成为泛型。因此,它需要一个完全不同的继承树。
所有 *CollectionBase 类的目的是为了在 .net 1.1 中提供实现强类型集合的基础。随着泛型在 2.0 中的引入,它们变得过时了,但是仍然保留在框架中以实现向后兼容性。

1

1
从非泛型基类继承会很低效。如果类型使用非泛型基类,它只是在基础集合之上添加了一个薄层,其中泛型特性仅从基础集合的底层object实例转换中派生。
这会导致值类型的不必要装箱/拆箱。使用泛型的好处之一是避免这种装箱/拆箱,这可能对集合的性能产生不利影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接