0

我为我的一个班级重写了 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;
}
4

2 回答 2

2

与 @Mitch Wheat 链接的内容一起,如果您将此类与 Dictionary 或 HashSet 一起使用,那并不是执行 GetHashCode() 的最佳方法。

想象一下,您的内部词典只有一个条目。您的哈希现在是该 single 的值KeyValuePair。你把整个班级都粘在一个HashSet. 您将另一个项目添加到您的内部Dictionary。现在您的班级的哈希码已更改,因为您正在迭代班级中的两个项目。

当您调用 时HashSet.Contains(obj),它会调用obj.GetHashCode()which 现在已更改,即使它是同一个类实例。 HashSet.Contains()会发现它不包含这个新的哈希并返回 false,从不调用 Equals(如果引用相同,它将返回 true)。

突然间,您的对象好像从 HashSet 中消失了,即使该类在其中,但散列已过时。

你真的不希望你的哈希改变。在你的 中发生碰撞是可以的GetHashCode,因为如果它发生碰撞,它会调用(较慢的).Equals()方法。这是一个方便的优化,如果实施不当,可能会在此过程中引起一些麻烦。

作为旁注,正如上面链接中所指出的,将散列乘以之前的素数^与另一个值是一个好主意。有助于保持独特性。

于 2011-07-30T02:52:15.997 回答
0

您打算在 HashSet 中使用该对象吗?如果要以这样一种方式使用对象,它要求它可以通过其哈希唯一标识,您实际上只需要实现 GetHashCode。考虑到在相等中使用的相同字段,始终实现 GetHashCode 是一种很好的做法,但并不总是必要的

如果您的情况有必要,我相信您的想法是正确的。

于 2011-07-30T02:44:28.697 回答