Yippie-Ki-Yay
Yippie-Ki-Yay

Reputation: 22794

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.

In the case of generic Equals method the example might look like this:

    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.

How should this be done?

Thank you.

Upvotes: 8

Views: 578

Answers (3)

jason
jason

Reputation: 241583

This is a terrible definition of Equals because it is not transitive.

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.

Additionally, we can establish that the only reasonable implementation of GetHashCode is a constant map.

Suppose that x and y are distinct objects. Let z be the object

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(). Since x and y were arbitrary we have established that GetHashCode is constant.

Thus, we have shown that the only possible implementation of GetHashCode is

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.

Upvotes: 18

Jon
Jon

Reputation: 437326

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. Putting objects of this type in a hash table is going to be painful.

Upvotes: 6

NerdFury
NerdFury

Reputation: 19214

I don't think you should be using Equals for this. 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". Maybe you need a different method like "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. Then they would be grouped.

Upvotes: 7

Related Questions