简体   繁体   English

C#GetHashCode问题

[英]C# GetHashCode question

What would be the best way to override the GetHashCode function for the case, when my objects are considered equal if there is at least ONE field match in them . 如果我的对象被认为是相等的,如果它们中至少有一个字段匹配,那么覆盖案例的GetHashCode函数的最佳方法是什么。

In the case of generic Equals method the example might look like this: 在通用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);
    }

Still, I'm confused about making a good GetHashCode implementation for this case. 尽管如此,我对于为这种情况制作一个好的GetHashCode实现感到困惑。

How should this be done? 该怎么做?

Thank you. 谢谢。

This is a terrible definition of Equals because it is not transitive. 这是对Equals的可怕定义,因为它不具有传递性。

Consider 考虑

x = { Id = 1, Money = 0.1, Code = "X" }
y = { Id = 1, Money = 0.2, Code = "Y" }
z = { Id = 3, Money = 0.2, Code = "Z" }

Then x == y and y == z but x != z . 然后x == yy == zx != z

Additionally, we can establish that the only reasonable implementation of GetHashCode is a constant map. 另外,我们可以确定GetHashCode的唯一合理实现是一个常量映射。

Suppose that x and y are distinct objects. 假设xy是不同的对象。 Let z be the object z为对象

z = { Id = x.Id, Money = y.Money, Code = "Z" }

Then x == z and y == z so that x.GetHashCode() == z.GetHashCode() and y.GetHashCode() == z.GetHashCode() establishing that x.GetHashCode() == y.GetHashCode() . 然后x == zy == z以便x.GetHashCode() == z.GetHashCode()y.GetHashCode() == z.GetHashCode()建立x.GetHashCode() == y.GetHashCode() Since x and y were arbitrary we have established that GetHashCode is constant. 由于xy是任意的,我们已经确定GetHashCode是常量。

Thus, we have shown that the only possible implementation of GetHashCode is 因此,我们已经证明GetHashCode唯一可能的实现是

private readonly int constant = 17;
public override int GetHashCode() {
    return constant;
}

All of this put together makes it clear that you need to rethink the concept you are trying model, and come up with a different definition of Equals . 所有这些放在一起表明你需要重新思考你正在尝试模型的概念,并提出不同的Equals定义。

I don't think you should be using Equals for this. 我不认为你应该使用Equals。 People have a very explicit notion of what equals means, and if the Ids are different but the code or name are the same, I would not consider those "Equal". 人们有一个非常明确的概念,即等于什么意思,如果ID不同但代码或名称相同,我不会认为那些“平等”。 Maybe you need a different method like "IsCompatible". 也许你需要一个像“IsCompatible”这样的不同方法。

If you want to be able to group them, you could use the extension method ToLookup() on a list of these objects, to use a predicate which would be your IsCompatible method. 如果您希望能够对它们进行分组,则可以在这些对象的列表上使用扩展方法ToLookup(),以使用谓词,该谓词将是您的IsCompatible方法。 Then they would be grouped. 然后他们将被分组。

The golden rule is: if the objects compare equal, they must produce the same hash code. 黄金法则是: 如果对象比较相等,则它们必须生成相同的哈希码。

Therefore a conforming (but let's say, undesirable) implementation would be 因此,符合(但假设,不合需要)的实现将是

public override int GetHashCode()
{
    return 0;
}

Frankly, if Id , Name and Code are independent of each other then I don't know if you can do any better. 坦率地说,如果IdNameCode彼此独立,那么我不知道你是否可以做得更好。 Putting objects of this type in a hash table is going to be painful. 将这种类型的对象放在哈希表中会很痛苦。

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

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