在==运算符覆盖中使用GetHashCode

时间:2012-01-26 00:10:29

标签: c#

只是想知道我在标题中提到的是一个好习惯。这对我来说很有意义,我们重写GetHashCode以返回一个基于两个属性的值,如果匹配,则应将两个对象视为相等。逻辑似乎很好,代码可以工作,但我不知道它是否会导致其他问题。

这是使用GetHashCode:

public static bool operator ==(CartesianCoordinates a, CartesianCoordinates b)
{
    return a.GetHashCode() == b.GetHashCode(); // Using GetHashCode here
}

public static bool operator !=(CartesianCoordinates a, CartesianCoordinates b)
{
    return !(a == b);
}

public override bool Equals(object obj)
{
    return this == (CartesianCoordinates)obj; // This just uses the == override
}

public override int GetHashCode()
{
    return (this.X + this.Y.ToLower()).GetHashCode(); // GetHashCode hashes the two properties we care about
}

这就是我以前的方式:

public static bool operator ==(CartesianCoordinates a, CartesianCoordinates b)
{
    return a.X == b.X && string.Equals(a.Y, b.Y, StringComparison.CurrentCultureIgnoreCase); // The difference is here
}

public static bool operator !=(CartesianCoordinates a, CartesianCoordinates b)
{
    return !(a == b);
}

public override bool Equals(object obj)
{
    return this == (CartesianCoordinates)obj;
}

public override int GetHashCode()
{
    return (this.X + this.Y.ToLower()).GetHashCode();
}

重要提示:

在CartesianCoordinates对象中,X是一个int,Y是一个字符串:

public int X { get; set; }
public string Y { get; set; }

Lmk,提前谢谢!

6 个答案:

答案 0 :(得分:8)

这样做不仅是不好的做法,只是错误!两个相等的对象必须具有相同的哈希码,但情况恰恰相反:两个不同的对象可以具有相同的哈希码(通常会)。因此,如果您使用哈希码来确定对象是否相等,在某些情况下,当它们实际上不同但恰好碰巧具有相同的哈希码时,您会认为它们相等。哈希码是唯一标识符...

根据您的GetHashCode实施情况,坐标为(x, y)(y, x)的对象将被视为相等(自x + y == y + x起)

答案 1 :(得分:4)

这是非常错误的 GetHashCode()不是唯一的。

您的特定示例更糟糕,因为您的GetHashCode()是可交换的。

答案 2 :(得分:3)

GetHashCode()可以为两个不相等的CartesianCoordinates返回相同的值,例如对于两个对象c1c2c1.x == c2.yc1.y == c2.x

对于更复杂的对象,如果hashCode是预先计算的,它可以用于短路,但最终你需要比较所有字段。这里的比较是微不足道的

答案 3 :(得分:0)

您的GetHashCode将返回{3,1}和{1,3}的相同值。我怀疑这不是故意的。

如果你的GetHashCode方法返回了更好的哈希码,我仍然建议不要使用GetHashCode作为相等比较。 GetHashCode合约表示具有相同跟踪属性的两个对象应该生成相同的哈希码,而不是具有相同哈希码的两个对象将是相等的。

编辑添加:

有关更好的实施情况的详细信息,请参阅此问题,尤其是Josh Bloch / Jon Skeet的回答。

答案 4 :(得分:0)

不,使用哈希码定义相等是不好的做法(甚至是正确的),因为不同的对象可能具有相同的哈希码(并且在String.GetHashCode的情况下肯定会发生)。

在您的特定情况下,还应注意您的GetHashCode方法甚至不匹配您的Equals方法,因为除{case}之外,GetHashCode将返回相同字符串的不同哈希码,而在这种情况下,您的Equals将返回true。

答案 5 :(得分:0)

您的GetHashCode()会为(2,4)(4,2)提供相同的结果。可能不是你想要的。

GetHashCode()通常也不是衡量平等的好方法。即使是非常好的哈希也只是一个32位整数。使用它来测试笛卡尔平面中的相等性将导致许多(无限数量)碰撞。