8

GetHashCode当我的对象被认为是相等的(如果它们中至少有一个字段匹配)时,覆盖该案例的函数的最佳方法是什么。

在泛型Equals方法的情况下,示例可能如下所示:

    public bool Equals(Whatever other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;

        // Considering that the values can't be 'null' here.
        return other.Id.Equals(Id) || Equals(other.Money, Money) ||
               Equals(other.Code, Code);
    }

不过,我对GetHashCode为这种情况做出良好的实施感到困惑。

这应该怎么做?

谢谢你。

4

3 回答 3

17

这是一个可怕的定义,Equals因为它不是传递的。

考虑

x = { Id = 1, Money = 0.1, Code = "X" }
y = { Id = 1, Money = 0.2, Code = "Y" }
z = { Id = 3, Money = 0.2, Code = "Z" }

然后x == yy == z但是x != z

此外,我们可以确定唯一合理的实现GetHashCode是常量映射。

假设xy是不同的对象。让z成为对象

z = { Id = x.Id, Money = y.Money, Code = "Z" }

然后x == zy == z那个x.GetHashCode() == z.GetHashCode()y.GetHashCode() == z.GetHashCode()建立那个x.GetHashCode() == y.GetHashCode()。由于x并且y是任意的,我们已经确定这GetHashCode是恒定的。

因此,我们已经证明唯一可能的实现GetHashCode

private readonly int constant = 17;
public override int GetHashCode() {
    return constant;
}

所有这些放在一起清楚地表明你需要重新考虑你正在尝试的模型的概念,并提出一个不同的定义Equals

于 2011-04-05T16:01:20.840 回答
7

我认为你不应该为此使用 Equals。人们对 equals 的含义有一个非常明确的概念,如果 Id 不同但代码或名称相同,我不会考虑那些“Equal”。也许您需要一种不同的方法,例如“IsCompatible”。

如果您希望能够对它们进行分组,您可以在这些对象的列表上使用扩展方法 ToLookup() 来使用您的 IsCompatible 方法的谓词。然后他们将被分组。

于 2011-04-05T15:57:08.120 回答
6

黄金法则是:如果对象比较相等,它们必须产生相同的哈希码。

因此,一个符合(但假设是不受欢迎的)实现将是

public override int GetHashCode()
{
    return 0;
}

坦率地说,如果IdName彼此Code独立,那么我不知道您是否可以做得更好。将这种类型的对象放入哈希表中会很痛苦。

于 2011-04-05T15:58:55.157 回答