我为我的一个类重写了Equals方法 . 在该方法中,我检查每对字典与另一个实例的字典的相等性,如下所示
public override bool Equals (object obj)
{
...
// compare to make sure all <key, value> pair of this.dict have
// the match in obj.dict
...
}
现在,我需要覆盖GetHashCode方法以及建议的内容 .
我是否需要为字典的所有键,或键加值?
基本上,以下是好还是矫枉过正?
public override int GetHashCode ()
{
int iHash = 0;
foreach (KeyValuePair<string, T> pair in this.dict)
{
iHash ^= pair.Key.GetHashCode();
iHash ^= pair.Value.GetHashCode();
}
return iHash;
}
2 回答
与@Mitch Wheat链接的一起,如果你将这个类与Dictionary或HashSet一起使用,那么这不是执行GetHashCode()的最佳方法 .
想象一下,你的内部词典只有一个条目 . 您的哈希值现在是单个
KeyValuePair
的值 . 你坚持整个 classHashSet
. 您将另一个项目添加到内部Dictionary
. 现在,您的类的哈希码已经更改,因为您正在迭代类中的两个项目 .当你调用
HashSet.Contains(obj)
时,它会调用现在已经改变的obj.GetHashCode()
,即使它是同一个类实例 .HashSet.Contains()
会发现它不包含这个新哈希并返回false,从不调用Equals(如果引用相同则返回true) .突然间它就像你的对象已经从HashSet中消失了,即使类在那里,有一个过时的哈希 .
你真的没有
GetHashCode
可以在GetHashCode
中发生碰撞,因为如果碰撞,它会调用(较慢的).Equals()
方法 . 这是一个方便的优化,如果实施不当,可能会导致一些令人头疼的问题 .作为旁注,正如上面的链接中所指出的,最好在
^
之前将散列乘以素数与另一个值 . 有助于保持独特 .你打算在HashSet中使用该对象吗?如果要以这样的方式使用对象,它需要通过其散列进行唯一标识,那么实际上只需要实现GetHashCode . 优良作法是始终实现GetHashCode,同时考虑相同使用的相同字段,但并非总是必要 .
如果您的情况有必要,我相信您有正确的想法 .