简体   繁体   English

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

[英]Using GetHashCode in == operator override

Just wondering if what I mentioned in the title is a good practice. 只是想知道我在标题中提到的内容是否是一种好习惯。 It makes sense to me, we're overriding GetHashCode to return a value based on two properties that if match, the two objects should be treated as equal. 对我而言,我们重写GetHashCode以基于两个属性返回值,如果两个属性匹配,则应将这两个对象视为相等。 Logic seems fine and the code works, but I don't know if it can cause other problems. 逻辑似乎很好并且代码可以正常工作,但是我不知道它是否会引起其他问题。

This is using 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
}

And this is how I had it before: 这就是我以前的经历:

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();
}

Important Note: 重要的提示:

In the CartesianCoordinates object, X is an int and Y is a string: 在CartesianCoordinates对象中,X是一个整数,Y是一个字符串:

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

Lmk, thanks in advance! Lmk,谢谢!

Doing this is not only bad practice, it's just wrong ! 这样做不仅是错误的做法,而且是错误的 Two objects that are equal must have the same hashcode, but the opposite is not true: two different objects can have the same hashcode (and often will). 两个相等的对象必须具有相同的哈希码,但事实却并非如此:两个不同的对象可以具有相同的哈希码(并且经常会)。 So if you use the hashcode to decide whether or not the objects are equal, in some case you will consider them equal when they're actually different but just happen to have the same hashcode. 因此,如果您使用哈希码确定对象是否相等,则在某些情况下,当它们实际上不同但恰好具有相同的哈希码时,您将认为它们相等。 A hashcode is not a unique identifier... 哈希码不是唯一标识符...

Based on your GetHashCode implementation, objects with coordinates (x, y) and (y, x) will be considered equal (since x + y == y + x ) 根据您的GetHashCode实现,坐标为(x, y)(y, x)将被视为相等(因为x + y == y + x

That is very wrong. 那是非常错误的。
GetHashCode() is not unique. GetHashCode()不是唯一的。

Your particular example is even worse, since your GetHashCode() is commutative. 您的特定示例甚至更糟,因为您的GetHashCode()是可交换的。

GetHashCode() can return same value for two CartesianCoordinates that are not equal, eg for two objects c1 and c2 such that c1.x == c2.y and c1.y == c2.x . 对于两个不相等的CartesianCoordinatesGetHashCode()可以返回相同的值,例如对于两个对象c1c2这样c1.x == c2.yc1.y == c2.x

For more complex objects and if the hashCode is pre-computed it can be used to short-circuit but eventually you will need to compare all fields. 对于更复杂的对象,如果hashCode是预先计算的,则可以将其用于短路,但最终您将需要比较所有字段。 Here the comparison is trivial 这里的比较是微不足道的

Your GetHashCode will return the same value for {3,1} and {1,3}. 您的GetHashCode将为{3,1}和{1,3}返回相同的值。 I suspect this is not intended. 我怀疑这不是故意的。

If your GetHashCode method returned a better hashcode, I'd still recommend against using GetHashCode as an equality comparison. 如果您的GetHashCode方法返回了更好的哈希码,我仍然建议不要将GetHashCode用作相等性比较。 The GetHashCode contract says that two objects with the same tracked properties should generate the same hashcode, not that two objects with equal hashcodes will be equal. GetHashCode合同规定,具有相同跟踪属性的两个对象应生成相同的哈希码,而不是具有相同哈希码的两个对象将相等。

Edit to add: 编辑添加:

See this question for details on what a better implementation looks like, particularly the Josh Bloch / Jon Skeet answer. 请参阅此问题,以获取有关更好的实现效果的详细信息,尤其是Josh Bloch / Jon Skeet的答案。

No, it's not good practice (or even correct) to define equality using the hash code since different objects may have the same hash code (and in the case of String.GetHashCode that can definitely happen). 不,使用哈希码定义相等性不是一个好习惯(甚至是正确的),因为不同的对象可能具有相同的哈希码(就String.GetHashCode而言,肯定会发生这种情况)。

In your particular case it should also be noted that your GetHashCode method doesn't even match your Equals method because your GetHashCode will return different hash codes for strings that are equal except for case, while your Equals will return true in that case. 在您的特殊情况下,还应该注意,您的GetHashCode方法甚至与Equals方法都不匹配,因为您的GetHashCode将为相等的字符串返回不同的哈希码(大小写除外),而在这种情况下,您的Equals将返回true。

Your GetHashCode() will give the same result for (2,4) and (4,2) . 您的GetHashCode()将为(2,4)(4,2)给出相同的结果。 Probably not what you want. 可能不是您想要的。

GetHashCode() is also generally not a good test for equality. GetHashCode()通常也不是对相等性的良好测试。 Even a really good hash is only a 32-bit integer. 即使是一个非常好的哈希也只有32位整数。 To use that to test for equality in the cartesian plane will result in many (an infinite number) of collisions. 用它来测试笛卡尔平面中的相等性将导致许多(无数)碰撞。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM