何时应使用IEqualityComparer? C#

时间:2018-10-23 19:01:58

标签: c# linq iequalitycomparer

我有一个试图删除重复记录的自定义对象列表。我看到太多在线文章指向IEqualityComparer(我以前从未使用过)。

问题是,我什么时候应该使用它?我可以通过LINQ在一行代码中获得相同的结果。

示例:

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;
    }
}

两者的结果:

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

3 个答案:

答案 0 :(得分:1)

以您的示例为例,假设您想比较忽略大小写的对象,以便将“ Apple”和“ apple”视为同一对象。然后您的ProductComparer可能像这样:

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.Equals(y.Name, StringComparison.InvariantCultureIgnoreCase));
    }

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

        var hashProductCode = product.Code.GetHashCode();

        return hashProductName ^ hashProductCode;
    }
}

它会产生与Linq不同的结果。

答案 1 :(得分:1)

  

我什么时候应该使用它?

一些可能性:

  • 当您对“平等”的定义比仅比较一个属性更为复杂时
  • 当您要预定义“平等”以便在许多查询中使用时
  • 当您要定义Linq的“平等” 外部时,例如使用类作为哈希表的键时
  • 当您想略微调整对等式的定义而无需重复代码(即打开/关闭区分大小写)

答案 2 :(得分:0)

大多数时候,可以使用一定数量的linq进行比较。如果是一次性的,那么选择可能仅取决于个人喜好。

如果比较逻辑被重用,创建IEqualityComparer是大多数API用来比较两个对象的一种标准且众所周知的方式。您可以在linq方法,集合等中重复使用实现。