Search code examples
c#linqiequalitycomparer

When should I use IEqualityComparer? C#


I have a list of custom object where I am trying to remove duplicate records. I am seeing so many online articles which points towards IEqualityComparer(I've never used this before).

Question is, when should I use it? I can achieve same result by LINQ in one line code.

Example:

public static void Main(string[] args)
{
    Product[] products =
    {
        new Product {Name = "apple", Code = 9},
        new Product {Name = "orange", Code = 4},
        new Product {Name = "apple", Code = 9},
        new Product {Name = "lemon", Code = 12}
    };

    // Using Custom comparer
    var usingCustomComparer = products.Distinct(new ProductComparer()).ToList();

    // Using LINQ
    var usinLinq = products.GroupBy(x => x.Name).Select(y => y.First()).ToList();
}

public class Product
{
    public string Name { get; set; }
    public int Code { get; set; }
}

// Custom comparer for the Product class
private class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product x, Product y)
    {
        if (ReferenceEquals(x, y)) return true;

        if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;

        return x.Code == y.Code && x.Name == y.Name;
    }

    public int GetHashCode(Product product)
    {
        var hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();

        var hashProductCode = product.Code.GetHashCode();

        return hashProductName ^ hashProductCode;
    }
}

Result from both:

{Name = "apple", Code = 9},
{Name = "orange", Code = 4},
{Name = "lemon", Code = 12}

Solution

  • when should I use it?

    Some possibilities:

    • When your definition of "equality" is more complicated than just comparing one property
    • When you want to pre-define "equality" for use in many queries
    • When you want to define "equality" outside of Linq, e.g. when using the class as the key to a hash table
    • When you want to tweak your definition of equality slightly without repeating code (i.e. turn on/off case sensitivity)