C# LINQ之IEqualityComparer<>接口应用

在C#语言中,对集合的条件查询、分组统计等操作使用LINQ非常方便,LINQ的语法格式与SQL非常相似和便捷,而LINQ扩展方法配合Lambda更为简洁,如All、Any、Count、MaxEnumerable类扩展方法,其中Distinct、Intersect、Contains等大量方法中使用了IEqualityComparer<>接口,以实现对象的比较,先看一个查询两个集合交集的代码示例:

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

// 产品类的自定义比较器
class ProductComparer : IEqualityComparer<Product>
{
	// 实现接口`Equals`方法
    public bool Equals(Product x, Product y)
    {
        // 比较两个对象的内存地址是否一致
        if (Object.ReferenceEquals(x, y)) return true;
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;
        return x.Code == y.Code && x.Name == y.Name;
    }
    
	// 实现接口`GetHashCode`方法
    public int GetHashCode(Product product)
    {
        if (Object.ReferenceEquals(product, null)) return 0;
        int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();
        int hashProductCode = product.Code.GetHashCode();
        return hashProductName ^ hashProductCode;
    }
}

static void Main(string[] args)
{
	// 初始化集合数据
    Product[] store1 = { new Product { Name = "apple", Code = 9 },
                         new Product { Name = "orange", Code = 4 } };
    Product[] store2 = { new Product { Name = "apple", Code = 9 },
                         new Product { Name = "lemon", Code = 12 } };
	
    // 查询store1与store2的交集    
    IEnumerable<Product> duplicates = store1.Intersect(store2, new ProductComparer());
    
    foreach (var product in duplicates)
    	Console.WriteLine(product.Name + " " + product.Code);
}

/*
    代码输出结果: apple 9
*/

看了以上代码后,有的小伙伴会问了,为什么要实现IEqualityComparer<>接口?实现IEqualityComparer<>接口需要注意什么?我来为大家解惑

1. 为什么要实现IEqualityComparer<>接口

是为了复杂类型(类)对象的比较,虽然store1[0]store2[0]的属性值都一样,但它们是两个不同的对象,如果GetHashCode方法代码如下,则结果为空。

public int GetHashCode(Product product)
{
    return product.GetHashCode();
}

2. 如何实现IEqualityComparer<>接口

首先,我们需要了解IEqualityComparer<>接口的两个方法的作用和逻辑,.NET处理时先比较两个对象GetHashCode方法返回的哈希值是否相等,如果不相等则直接返回,不再执行Equals方法,如果哈希值相等则执行Equals方法继续比较!为什么要用两个方法去对比呢?原因是GetHashCode方法比Equals方法效率更高,所以先执行GetHashCode方法。依据上述分析,把示例中GetHashCode方法改为如下代码,则结果是相同的。

public int GetHashCode(Product product)
{
    return 0;
}
原文地址:https://www.cnblogs.com/zhaoshujie/p/14724710.html