为什么HashSet<T>没有实现ICollection接口?

8
我将编写一个库来遍历对象图(类似某种序列化)。
在遍历过程中,您需要判断对象是否为集合,因此我想到了 ICollection。(string 也实现了 IEnumerable
但是,几乎所有的容器集合都已经实现了 ICollection,唯独 HashSet 只实现了 ICollection<T>……
我已经检查了 System.Collections 命名空间中的几乎所有常见容器集合:
ArrayList : IList, ICollection, IEnumerable, ICloneable  
BitArray : ICollection, IEnumerable, ICloneable  
Hashtable : IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback, ICloneable  
Queue : ICollection, IEnumerable, ICloneable  
SortedList : IDictionary, ICollection, IEnumerable, ICloneable  
Stack : ICollection, IEnumerable, ICloneable  
Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable, IDeserializationCallback
HashSet<T> : ISerializable, IDeserializationCallback, ISet<T>, ICollection<T>, IEnumerable<T>, IEnumerable  
LinkedList<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable, ISerializable, IDeserializationCallback  
List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable  
Queue<T> : IEnumerable<T>, ICollection, IEnumerable  
SortedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable  
SortedList<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable  
SortedSet<T> : ISet<T>, ICollection<T>, IEnumerable<T>, ICollection, IEnumerable, ISerializable, IDeserializationCallback  
Stack<T> : IEnumerable<T>, ICollection, IEnumerable  

这是一个BUG吗?还是有其他原因导致的?


2
我认为这个链接与你的问题相关。 - Saragis
2
.NET的集合层次结构真的很混乱。 - usr
3
如果您正在将1.1代码升级到2.0,则List<T>实现ICollection显然有助于替换旧的ArrayList用法(理论上最好只是让编译器出现错误,指向需要升级为ICollection<T>的位置)。在引入3.5之前,HashSet<T>没有非泛型版本,因此支持ICollection与其他大多数集合类型不同。 - Jon Hanna
1
@JonHanna 但是SortedSet<>是一种更新的类型,它确实实现了非泛型的ICollection吗? - Jeppe Stig Nielsen
1
对应的元帖:http://meta.stackoverflow.com/questions/293815/is-it-subjective-to-ask-about-why-something-wasnt-implemented-in-the-language - Binkan Salaryman
1
@JeppeStigNielsen 没错,但你可以争论它不应该这样。就此而言,你可以争论 List<T> 也不应该这样,但是对于 HashSet<T>SortedSet<T>,你会有更强的理由。这是设计决策,因此更多的是关于你能够争论出什么作为某人所争论的线索,而不是自然界中不可变的法则。 - Jon Hanna
1个回答

0

ICollection在.NET 1.1时非常有用,因为没有ICollection<T>提供更大的类型安全性。现在很少有什么可以用ICollection有用地完成而ICollection<T>不能完成,尤其是当你编写通用方法去处理不同元素类型的集合的情况下,使用ICollection<T>会更加高效和类型安全。

这引出了一个问题,为什么像 List<T> 这样的类实现了 ICollection 接口。但是当 .NET 2.0 引入 List<T> 时,所有遗留代码都在使用 ICollectionArrayList,而不是 ICollection<T>List<T>。将代码升级为使用 List<T> 而不是 ArrayList 可能会很麻烦,特别是如果这意味着必须立即更改所有使用 ICollection 的地方以使用 ICollection<T> 或者更糟糕的是,因为一个方法被 List<T> 和其他非泛型集合同时调用,所以每个版本的方法都需要。实现 ICollection 接口可以通过允许人们更分散地利用泛型集合来简化升级路径。

HashSet<T> 出现时,泛型已经使用了三年,并且框架中没有提供先前的非泛型哈希集类型,因此升级的痛苦较小,因此支持 ICollection 的动机也较少。


1
ICollection非常有用,可以确定对象是有限的非惰性集合。大多数人只使用IEnumerable来确定对象是某种类型的集合,但IEnumerable可能是惰性和/或无限的。因此,ICollection是几乎所有有限的非惰性集合支持的最小接口。但很烦人的是,像HashSet<T>、ImmutableQueue<T>、ImmutableStack<T>这样的集合却不支持它。 - Yuri Bondarchuk

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