C# – What’s the recommended best practice for using IEqualityComparer


I'm looking for real world best practices, how other people might have implemented solutions with complex domains.

Best Solution

Any time you consider using an IEqualityComparer<T>, pause to think if the class could be made to implement IEquatable<T> instead. If a Product should always be compared by ID, just define it to be equated as such so you can use the default comparer.

That said, there are still a few of reasons you might want a custom comparer:

  1. If there are multiple ways instances of a class could be considered equal. The best example of this is a string, for which the framework provides six different comparers in StringComparer.
  2. If the class is defined in such a way that you can't define it as IEquatable<T>. This would include classes defined by others and classes generated by the compiler (specifically anonymous types, which use a property-wise comparison by default).

If you do decide you need a comparer, you can certainly use a generalized comparer (see DMenT's answer), but if you need to reuse that logic you should encapsulate it in a dedicated class. You could even declare it by inheriting from the generic base:

class ProductByIdComparer : GenericEqualityComparer<ShopByProduct>
    public ProductByIdComparer()
        : base((x, y) => x.ProductId == y.ProductId, z => z.ProductId)
    { }

As far as use, you should take advantage of comparers when possible. For example, rather than calling ToLower() on every string used as a dictionary key (logic for which will be strewn across your app), you should declare the dictionary to use a case-insensitive StringComparer. The same goes for the LINQ operators that accept a comparer. But again, always consider if the equatable behavior that should be intrinsic to the class rather than defined externally.