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