0

When using IEqualityComparer to compare objects in a collection, I'm not sure which one of the followings approaches is the best one.

Here is the implementation :

class CarComparer : IEqualityComparer<Car>
{
    public bool Equals(Car x, Car y)
    {
        throw new NotImplementedException();
    }

    public int GetHashCode(Car car)
    {
        //
    }
}

And here are my two options for GetHashCode implementation

    public int GetHashCode(Car row)
    {
        return HashCode.Combine(row.Name, row.Color , row.Size);
    }

Or,

    public int GetHashCode(Car row)
    {
        return row.GetHashCode();
    }

I don't like the first one because it make code less maintainable and probably less expensive in terms of resources. But a lot of people use it like that.

I would like to use my CarComparer in linq functions later. Like this:

cars.Distinct(new CarComparer());

Which one should I use?

Is this an opinion based question?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
BorisD
  • 1,611
  • 17
  • 22
  • 2
    Presumably you're implementing an `IEqualityComparer` because `Car` itself does not implement `GetHashCode` and `Equals` the way you want it to (that's basically the only reason you'd write an `IEqualityComparer`). In that case, surely `Car.GetHashCode()` doesn't do what you want, and therefore there's no point in delegating to it – canton7 Jun 22 '21 at 12:38
  • Yes @canton7, for example using the .Distinct() method would not work without a custom comparer (linq) – BorisD Jun 22 '21 at 12:42
  • 2
    If you want to use the implementation of `Car`'s `GetHashCode` and `Equals` there's no reason to implement a custom `IEqualityComparer`. You should implement that interface if you need a custom logic to compare your objects. So override `Equals` and `GetHashCode` then. – Tim Schmelter Jun 22 '21 at 12:43
  • thanks @TimSchmelter please see my answer to canton7 comment – BorisD Jun 22 '21 at 12:44
  • 2
    @BorisDetry Your comment doesn't help I'm afraid. Do you want to use `Car`'s implementation of `GetHashCode` or not? If you want to use it, you don't need a custom `IEqualityComparer`. If you don't want to use it, don't call it (from within your `IEqualityComparer`) – canton7 Jun 22 '21 at 12:45
  • @BorisDetry: answered that in my answer – Tim Schmelter Jun 22 '21 at 12:47
  • I did a little update on the question @canton7, hope it helps – BorisD Jun 22 '21 at 12:47
  • 2
    @BorisDetry Why don't you override `Equals` and `GetHashCode` in your `Car` class? That way you don't need an `IEqualityComparer` – canton7 Jun 22 '21 at 13:00
  • @canton7 I guess that should work too, but how do I implement GetHashCode() in car class? Way one or two? – BorisD Jun 22 '21 at 13:06
  • 3
    @BorisDetry Well, calling `this.GetHashCode()` inside your Car's `GetHashCode()` method would lead to a stack overflow.... Calling `base.GetHashCode()` does exactly the same thing as not overriding it at all, which is obviously pointless. – canton7 Jun 22 '21 at 13:08

1 Answers1

0

The correct answer:

When using LINQ the GetHashCode is called before the Equals method and only when the result of the GetHashCode is equal for two items in the collection.

So GetHashCode must be override too :

  public int GetHashCode(Car row)
{
    return HashCode.Combine(row.Name, row.Color , row.Size);
}

See full response here

BorisD
  • 1,611
  • 17
  • 22