我有以下对象。
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.
我需要两者相同。
答案 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可能是一种更聪明的方法,但你明白了。