1

I am trying to understand the difference between two overloads of Enumerable.Except method i.e.

  • Except(IEnumerable, IEnumerable)
  • Except(IEnumerable, IEnumerable, IEqualityComparer)

Obviously, the first differnce is that the first overload uses the default equality comparer while the other uses an IEqualityComparer, but I can achieve the same result with first method, by implementing an IEquatable interface (as mentioned in the MSDN documentation of Except method), then why this second overload is needed?

Coder23
  • 128
  • 8
  • Well, just for the cases when you can't implement `IEquatable` interface by some reason (for example - if it's not your class), but still want to use custom comparer. – Andrey Korneyev Dec 11 '14 at 11:44
  • Maybe you want to use it on 2 `IEnuemrable` but you cannot modify `SomeThirdPartyClass`, then you must use the second overload. – Ben Robinson Dec 11 '14 at 11:44
  • Sometimes there are several applicable equality rules for an object, depending on the context. IEquatable really provides one use case, so in those situations, you need to define the alternative comparer, and the second overload of `Except`. – code4life Dec 11 '14 at 11:59

1 Answers1

11

Two reasons:

  1. You can only implement IEquatable<T> for your own types... whereas you can specify an IEqualityComparer<T> for any type, whether you can modify it yourself or not.

  2. There may be multiple ways of comparing a type for equality, but implementing IEquatable<T> only allows you to express one of them.

A simple example of all of this would be strings - consider:

string[] x = { "A", "B", "C" };
string[] y = { "A", "c" };

var bc = x.Except(y);
var justB = x.Except(y, StringComparer.OrdinalIgnoreCase);

We might want both results in different circumstances, which means we couldn't handle both with IEquatable<T>... and we can't change how string implements IEquatable<T> anyway. (You're not limited to StringComparer of course - you could write an equality comparer which just used the length of the string, for example.)

This isn't specific to LINQ, either - it's generally the case for any API which deals in equality, e.g. HashSet<>, Dictionary<,> etc.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194