简体   繁体   English

我什么时候应该使用 IEqualityComparer? C#

[英]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).我看到很多指向IEqualityComparer在线文章(我以前从未使用过)。

Question is, when should I use it?问题是,我应该什么时候使用它? I can achieve same result by LINQ in one line code.我可以在一行代码中通过LINQ实现相同的结果。

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}

Going with your example, say that you wanted to compare the objects ignoring case, so that "Apple" and "apple" would be considered the same object.以您的示例为例,假设您想比较忽略大小写的对象,以便将“Apple”和“apple”视为同一个对象。 Then your ProductComparer may look like:那么您的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;
    }
}

And it would yield different results than Linq.它会产生与 Linq 不同的结果。

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, eg when using the class as the key to a hash table当您想Linq之外定义“相等”时,例如当使用类作为哈希表的键时
  • When you want to tweak your definition of equality slightly without repeating code (ie turn on/off case sensitivity)当您想在不重复代码的情况下稍微调整相等性的定义时(即打开/关闭区分大小写)

Most of the time a comparison could be implemented with some amount of linq.大多数情况下,可以使用一定量的 linq 进行比较。 If it's one-off, the choice is probably just down to personal preference.如果是一次性的,选择可能只是取决于个人喜好。

If the comparison logic is re-used a fair amount, creating a IEqualityComparer is a standard and well-known way accepted by most APIs for comparing two objects.如果比较逻辑被大量重复使用,则创建IEqualityComparer是大多数 API 接受的用于比较两个对象的标准和众所周知的方式。 You can re-use the implementation in linq methods, collections, etc.您可以在 linq 方法、集合等中重用实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM