【问题标题】:GetHashCode for Dictionary items字典项目的 GetHashCode
【发布时间】:2011-07-30 02:18:27
【问题描述】:

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

【问题讨论】:

标签: c# dictionary gethashcode


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 这是一个有效的担忧。如果字典是不可变的怎么办?那会不会出现您上面指出的问题?
  • 如果键/值对永远不会改变,我的意思是不会添加或删除KeyValuePairs,以及每个KeyValuePair 的实际键和值都不会得到改变,那么是的,你不必担心它。请记住,在每个KeyValuePair 内部,key 或 value 可以是一个类,并且该类可以是可变的,如果更改,则输出不同的 HashCode
【解决方案2】:

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

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

【讨论】:

  • 酷。这就是我想知道的。这纯粹是为了独特。
  • 很高兴我能帮上忙。如果这对您来说是一个满意的答案,如果您将此标记为答案,我们将不胜感激。 :)
猜你喜欢
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 2019-08-24
相关资源
最近更新 更多