比较对象,忽略" order"成员

时间:2017-08-05 00:06:04

标签: c#

我有以下对象。

public class Foo
{
    public int X { get; }
    public int Y { get; }

    public Foo(int x, int y)
    {
        this.X = x;
        this.Y = y;
    }
}

现在我想覆盖Equals和GetHashCode方法,这两个对象应该被视为相等(和相同的哈希码)。

var foo1 = new Foo(1, 2);
var foo2 = new Foo(2, 1);

我知道如何编写Equals方法,但我很难使用get hashcode方法。

这是我目前的版本:

public override int GetHashCode()
{
    unchecked
    {
        return (_x * 397) ^ _y;
    }
}

在我当前的 - 不工作的解决方案中 - foo1的HashCode为399,foo2为795.

我需要两者相同。

1 个答案:

答案 0 :(得分:5)

您需要进行转化,f(x,y) = f(y,x)。我可以想到一些应该做的数学属性 - 任何可交换的东西都应该起作用,例如:简单的乘法。

public override int GetHashCode()
{
    unchecked
    {
        return _x * _y;
    }
}

不确定收敛的可能性,并且对于大量字段来说可能更棘手。作为替代方法,您可以在散列之前将可交换参数强制为已排序的顺序:

public override int GetHashCode()
{
    var x = Math.Min(_x, _y);
    var y = Math.Max(_x, _y);
    unchecked
    {
        return (x * 397) ^ y;
    }
}

或者,如果您有三个或更多字段:

public override int GetHashCode()
{
    var a = new int[] { _x, _y, _z };
    Array.Sort(a);
    unchecked
    {
        return ((a[0] * 397) ^ a[1]) * 397 ^ a[2];
    }
}

使用LINQ可能是一种更聪明的方法,但你明白了。