字典项的GetHashCode

时间:2011-07-30 02:18:27

标签: c# dictionary gethashcode

我为我的一个类重写了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 :(得分:1)

与@Mitch Wheat链接的一起,如果你将这个类与Dictionary或HashSet一起使用,这不是做GetHashCode()的最好方法。

想象一下,你的内部词典只有一个条目。您的哈希值现在是该单个KeyValuePair的值。你把全班都放在HashSet中。您将另一个项目添加到内部Dictionary。现在你的类的哈希码已经改变,因为你正在迭代你班上的两个项目。

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

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

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

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

答案 1 :(得分:0)

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

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