什么时候应该使用 IEqualityComparer? C#
When should I use IEqualityComparer? C#
我有一个自定义对象列表,我试图在其中删除重复记录。我看到很多在线文章都指向 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}
继续你的例子,假设你想比较忽略大小写的对象,这样 "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 不同的结果。
大多数情况下,可以使用一定数量的 linq 进行比较。如果是一次性的,选择可能只是取决于个人喜好。
如果比较逻辑被大量重复使用,创建 IEqualityComparer
是大多数 API 接受的用于比较两个对象的标准且众所周知的方法。您可以在 linq 方法、集合等中重复使用该实现。
when should I use it?
一些可能性:
- 当您对 "equality" 的定义比仅比较一个 属性
更复杂时
- 当您想预定义 "equality" 以用于许多查询时
- 当您想在 Linq 的 "equality" 之外定义时,例如当使用 class 作为散列的键时 table
- 当您想在不重复代码的情况下稍微调整相等性的定义时(即 on/off 区分大小写)
我有一个自定义对象列表,我试图在其中删除重复记录。我看到很多在线文章都指向 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}
继续你的例子,假设你想比较忽略大小写的对象,这样 "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 不同的结果。
大多数情况下,可以使用一定数量的 linq 进行比较。如果是一次性的,选择可能只是取决于个人喜好。
如果比较逻辑被大量重复使用,创建 IEqualityComparer
是大多数 API 接受的用于比较两个对象的标准且众所周知的方法。您可以在 linq 方法、集合等中重复使用该实现。
when should I use it?
一些可能性:
- 当您对 "equality" 的定义比仅比较一个 属性 更复杂时
- 当您想预定义 "equality" 以用于许多查询时
- 当您想在 Linq 的 "equality" 之外定义时,例如当使用 class 作为散列的键时 table
- 当您想在不重复代码的情况下稍微调整相等性的定义时(即 on/off 区分大小写)