在C#语言中,对集合的条件查询、分组统计等操作使用LINQ
非常方便,LINQ
的语法格式与SQL
非常相似和便捷,而LINQ
扩展方法配合Lambda
更为简洁,如All、Any、Count、Max
等Enumerable
类扩展方法,其中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;
}