首页 文章

字典项的GetHashCode

提问于
浏览
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;
}

2 回答

  • 0

    与@Mitch Wheat链接的一起,如果你将这个类与Dictionary或HashSet一起使用,那么这不是执行GetHashCode()的最佳方法 .

    想象一下,你的内部词典只有一个条目 . 您的哈希值现在是单个 KeyValuePair 的值 . 你坚持整个 class HashSet . 您将另一个项目添加到内部 Dictionary . 现在,您的类的哈希码已经更改,因为您正在迭代类中的两个项目 .

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

    突然间它就像你的对象已经从HashSet中消失了,即使类在那里,有一个过时的哈希 .

    你真的没有 GetHashCode 可以在 GetHashCode 中发生碰撞,因为如果碰撞,它会调用(较慢的) .Equals() 方法 . 这是一个方便的优化,如果实施不当,可能会导致一些令人头疼的问题 .

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

  • 1

    你打算在HashSet中使用该对象吗?如果要以这样的方式使用对象,它需要通过其散列进行唯一标识,那么实际上只需要实现GetHashCode . 优良作法是始终实现GetHashCode,同时考虑相同使用的相同字段,但并非总是必要 .

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

相关问题