What's the recommended best practice for using IEqualityComparer<T>?

c#, comparison

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:

- 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`.

- 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.

Problem

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

Original source

Related problems