为啥 HashSet<T> 没有实现 ICollection?

Posted

技术标签:

【中文标题】为啥 HashSet<T> 没有实现 ICollection?【英文标题】:Why does HashSet<T> not implement ICollection?为什么 HashSet<T> 没有实现 ICollection? 【发布时间】:2015-09-25 04:52:03 【问题描述】:

我将编写一个库来遍历对象图(例如某种序列化)。 您需要判断一个对象是否是遍历中的一个集合,所以ICollection 出现在我的脑海中。 (string也实现了IEnumerable

但是真的很奇怪,Collections 中几乎所有的容器都实现了ICollection 除了HashSet 只实现了ICollection&lt;T&gt;...

我已经检查了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  

这是一个错误吗?还是有什么原因?

【问题讨论】:

我相信this link 与您的问题相关。 .NET 集合层次结构真的很乱。 如果您将 1.1 代码升级到 2.0,那么 List&lt;T&gt; 实现 ICollection 可以说可以帮助您替换 ArrayList 的旧用法(可以说让编译器错误指向哪里会更好)您需要升级到ICollection&lt;T&gt;)。 HashSet&lt;T&gt; 在 3.5 引入之前没有非通用版本,因此支持 ICollection 和其他大多数人的原因之一不存在。 @JonHanna 但是SortedSet&lt;&gt; 是一个更新的类型,它确实实现了非泛型ICollection? 对应元帖:meta.***.com/questions/293815/… 【参考方案1】:

ICollection 现在远没有 .NET 1.1 那样有用,当时还没有 ICollection&lt;T&gt; 提供更高的类型安全性。很少有人可以用ICollection 做有用的事情而用ICollection&lt;T&gt; 做不到,通常效率和/或类型安全性更高,特别是如果为那些可能想要对集合做某事的情况编写通用方法时不同的元素类型。

这虽然引出了一个问题,为什么List&lt;T&gt; 之类的人确实 实现了ICollection。但是当List&lt;T&gt; 与.NET 2.0 一起引入时,所有遗留代码都使用ICollectionArrayList,而不是ICollection&lt;T&gt;List&lt;T&gt;。将代码升级为使用List&lt;T&gt; 而不是ArrayList 可能会很痛苦,尤其是如果这意味着必须立即更改ICollection 的所有用法,使用ICollection&lt;T&gt; 或者更糟糕的是,因为一种方法而加倍被List&lt;T&gt; 击中,也被其他非泛型集合击中,因此每个版本都需要该方法的版本。实施 ICollection 让人们可以更加零碎地利用通用集合,从而简化了升级路径。

HashSet&lt;T&gt; 出来的时候,泛型已经使用了三年了,并且没有框架提供以前的非泛型哈希集类型,所以升级的痛苦更少,因此更少支持ICollection的动机。

【讨论】:

ICollection 对于确定对象是有限非惰性集合非常有用。大多数人只是使用 IEnumerable 来确定对象是某种集合,但 IEnumerable 可以是惰性的和/或无限的。所以 ICollection 是几乎所有有限非惰性集合都支持的最小接口。很烦人的是很少有像 HashSet、ImmutableQueue、ImmutableStack 这样的集合没有。

以上是关于为啥 HashSet<T> 没有实现 ICollection?的主要内容,如果未能解决你的问题,请参考以下文章

为啥许多编程语言中的集合不是真正的集合?

C#中List怎么转换成hashset

SortedSet<T> 与 HashSet<T>

克隆 HashSet<T> 的有效方法?

什么时候应该使用 HashSet<T> 类型?

C# HashSet<T> 只读解决方法