我需要使用我编写的类作为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会使用哈希码吗?如果是,它来自哪里?否则,我的词典会不会有成本访问操作(我不认为没有哈希码就可以实现)
答案 0 :(得分:4)
但是我很惊讶System.IEquatable没有HashCode()方法。
System.IEquatable<T>
将HashCode方法作为System.Object(您的实现类将隐式继承)已经提供了方法GetHashCode
答案 1 :(得分:1)
是的,字典将使用哈希码。字典实际上是封面下的哈希映射。
它将使用的哈希码实现是由密钥中的GetHashCode
实现的哈希代码实现。如果您没有自己定义实现,则哈希代码将基于引用类型的引用,以及值类型(结构)的各个字段。当使用您自己的类作为字典中的键时,建议实现GetHashCode
。
实施IEquatable<T>
时,您必须覆盖对象上的Equals
和GetHashCode
以匹配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。很多碰撞。