什么是使用的IEqualityComparer<推荐的最佳做法; T> ;?

什么是使用的IEqualityComparer<推荐的最佳做法; T> ;?

问题描述:

我正在寻找现实世界中的最佳实践,别人怎么可能有复杂的领域实施的解决方案。

I'm looking for real world best practices, how other people might have implemented solutions with complex domains.

任何时候你可以考虑使用的IEqualityComparer&LT; T&GT; ,停下来想,如果这个类可以作出实施 IEquatable&LT; T&GT; 来代替。如果产品应该总是通过ID进行比较,只是把它定义为等同这样,所以你可以使用默认的比较。

Any time you consider using an IEqualityComparer<T>, pause to think if the class could be made to implement IEquatable<T> instead. If a Product should always be compared by ID, just define it to be equated as such so you can use the default comparer.

不过,还是有一些原因,你可能想自定义比较:

That said, there are still a few of reasons you might want a custom comparer:


  1. 如果有多种方式实例一类可被认为是相等的。这样做的最好的例子是一个字符串,为此,该框架提供的 StringComparer

  2. 如果该类以这样的方式定义的,你不能把它定义为 IEquatable&LT; T&GT; 。这将包括由编译器(特别是匿名类型,默认情况下使用属性明智的比较)产生别人和类定义的类。

  1. If there are multiple ways instances of a class could be considered equal. The best example of this is a string, for which the framework provides six different comparers in StringComparer.
  2. If the class is defined in such a way that you can't define it as IEquatable<T>. This would include classes defined by others and classes generated by the compiler (specifically anonymous types, which use a property-wise comparison by default).

如果你决定你需要一个比较器,你当然可以用广义的比较器(见DMenT的答案),但如果你需要重新使用逻辑应该封装在一个专用的类。你甚至可以通过从通用基继承声明它:

If you do decide you need a comparer, you can certainly use a generalized comparer (see DMenT's answer), but if you need to reuse that logic you should encapsulate it in a dedicated class. You could even declare it by inheriting from the generic base:

class ProductByIdComparer : GenericEqualityComparer<ShopByProduct>
{
    public ProductByIdComparer()
        : base((x, y) => x.ProductId == y.ProductId, z => z.ProductId)
    { }
}

至于使用,您应该利用comparers的可能时。例如,而不是调用 ToLower将()在作为字典的键每个字符串(其逻辑将在您的应用程序,简直是俯拾即是),你应该申报字典使用不区分大小写 StringComparer 。这同样适用于LINQ的运营商接受一个比较器。但同样,始终考虑如果equatable行为应该是内在的类,而不是外部定义的。

As far as use, you should take advantage of comparers when possible. For example, rather than calling ToLower() on every string used as a dictionary key (logic for which will be strewn across your app), you should declare the dictionary to use a case-insensitive StringComparer. The same goes for the LINQ operators that accept a comparer. But again, always consider if the equatable behavior that should be intrinsic to the class rather than defined externally.