C#GetHashCode问题

Yip*_*Yay 8 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);
    }
Run Code Online (Sandbox Code Playgroud)

尽管如此,我GetHashCode对这个案例的良好实施感到困惑.

该怎么做?

谢谢.

jas*_*son 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" }
Run Code Online (Sandbox Code Playgroud)

然后x == y,y == z但是x != z.

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

假设x并且y是不同的对象.让我们z成为对象

z = { Id = x.Id, Money = y.Money, Code = "Z" }
Run Code Online (Sandbox Code Playgroud)

然后x == zy == zx.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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 好点子.更一般地说,平等应该是*等价关系*.也就是说,它应该是*自反*(x等于x总是为真),*对称*(x等于y与y等于x相同)和*传递*(如果x等于y且y等于z然后x等于z ).请注意,在C#中,不同类型*的等式*不是等价关系; 比较为字符串的两个字符串在作为对象比较时可能会产生不同的结果 在少数情况下,等式不是类型中的等价关系(例如,Double.NaN!= Double.NaN).但最好是努力使等式成为等价关系. (3认同)

Ner*_*ury 7

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

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


Jon*_*Jon 6

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

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

public override int GetHashCode()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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