默认构造函数创建的`Dictionary`是否使用哈希码?

时间:2012-11-14 19:13:23

标签: c# .net dictionary

我需要使用我编写的类作为Dictionary的键的类型

我读了documentation on MSDN about the default constructor of Dictionary

  

Dictionary<TKey, TValue>需要实现相等的实现   确定键是否相等。此构造函数使用默认值   通用等式比较器,EqualityComparer<T>.Default。如果输入   TKey实现了System.IEquatable<T>通用接口   default equality comparer使用该实现。或者,你   可以指定IEqualityComparer<T>泛型的实现   通过使用接受比较器参数的构造函数进行接口。

这让我觉得我唯一要做的就是让我的班级成为关键工具System.IEquatable<T>

但是我很惊讶System.IEquatable<T>没有HashCode()方法。

这样创建的Dictionary会使用哈希码吗?如果是,它来自哪里?否则,我的词典会不会有成本访问操作(我不认为没有哈希码就可以实现)

4 个答案:

答案 0 :(得分:4)

  

但是我很惊讶System.IEquatable没有HashCode()方法。

System.IEquatable<T>将HashCode方法作为System.Object(您的实现类将隐式继承)已经提供了方法GetHashCode

,这将是多余的。

答案 1 :(得分:1)

是的,字典将使用哈希码。字典实际上是封面下的哈希映射。

它将使用的哈希码实现是由密钥中的GetHashCode实现的哈希代码实现。如果您没有自己定义实现,则哈希代码将基于引用类型的引用,以及值类型(结构)的各个字段。当使用您自己的类作为字典中的键时,建议实现GetHashCode

实施IEquatable<T>时,您必须覆盖对象上的EqualsGetHashCode以匹配IEquatable<T>的实施。它不在界面中的原因是GetHashCode已在object上定义,所有类都派生自,因此在界面中使用它不会产生任何影响。

如果您未能实现GetHashCode以使其与IEquatable<T>实施相匹配,则可能会遇到将密钥放入字典但无法再次检索的问题,因为哈希代码不匹配:当字典查找密钥时,它首先在该密钥上调用GetHashCode。从这里开始,字典派生出密钥所在的内部bucket。然后它查看该特定存储桶中的所有密钥并调用Equals以找到正确的密钥。

答案 2 :(得分:1)

它仍然使用重写的object.GetHashCode()方法来获取哈希码。有一个单独的IEquatable<T>接口的原因(即为什么默认的EqualityComparer<T>并不总是只调用重写的object.Equals()方法来比较两个对象)是出于性能原因 - {{1采用object.Equals()参数,因此实现必须先将其转换为目标类型才能执行有意义的比较(值类型也必须加框和取消装箱);而object的参数已经是IEquatable<T>.Equals()类型。此性能考虑不适用于T方法,因为它不带参数,因此没有理由在GetHashCode()接口上存在。

答案 3 :(得分:0)

Dictionary(HashSet和KeyedCollections)都使用HashBuckets(速度) HashBuckets使用GetHashCode,它是Int32。

如果对象不相等,则它们必须具有不同的GetHashCode 但是两个不相等的对象可能具有相同的GetHashCode。

如果GetHashCode相同,那么平局判断为Equals GetHashCode比较更快 - 你想避免打破平局。

你想要一个好的(独特的)GetHashCode 如果对象来自数据库并且表具有键并且该键是Int32(或更少),那么使用它来获得完美的哈希码。

如果您的对象没有自然键,则可以使用系统GetHashCode 但是如果你有一个自然键然后使用它。

所有对象实现Object Object Class
如果您的类没有覆盖GetHashCode,那么它将来自Object。

为Key提供针对Tuple或KeyValuePair的建议,因为它们不会产生良好的GetHashCode。很多碰撞。