C#GetHashCode问题

时间:2011-04-05 15:53:06

标签: c# properties equals matching gethashcode

什么是覆盖案例的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实施感到困惑。

应如何做?

谢谢。

3 个答案:

答案 0 :(得分: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()。由于xy是任意的,我们已确定GetHashCode是常数。

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

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

所有这些结合在一起表明你需要重新思考你正在尝试模型的概念,并提出Equals的不同定义。

答案 1 :(得分:7)

我认为你不应该使用Equals。人们有一个非常明确的概念,即等于什么意思,如果ID不同但代码或名称相同,我不会认为那些“平等”。也许你需要一种不同的方法,比如“IsCompatible”。

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

答案 2 :(得分:6)

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

因此,符合(但假设,不合需要)的实施将是

public override int GetHashCode()
{
    return 0;
}

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