使用IEqualityComparer< T>的推荐最佳做法是什么? [英] What's the recommended best practice for using IEqualityComparer<T>?
问题描述
我在寻找现实世界的最佳实践,其他人可能已经实施了复杂域的解决方案。时间你考虑使用 IEqualityComparer< T>
,暂停考虑该类是否可以实现 IEquatable< T>
改为。如果产品
应始终通过ID进行比较,只需将其定义为等同,以便可以使用默认比较器。
也就是说,仍然有几个原因你可能想要一个自定义的比较器:
- 如果有多个方法实例一个类可以被认为是平等的。最好的例子是一个字符串,框架在
StringComparer
。 - 如果类的定义方式不能定义为
IEquatable< T>
。这将包括由其他人定义的类和由编译器生成的类(特别是匿名类型,默认情况下使用属性比较)。
如果你确定需要一个比较器,你一定可以使用一个广义比较器(见DMenT的答案),但如果你需要重用这个逻辑,你应该把它封装在一个专门的类。你甚至可以通过继承泛型基础来声明它:
class ProductByIdComparer:GenericEqualityComparer< ShopByProduct>
{
public ProductByIdComparer()
:base((x,y)=> x.ProductId == y.ProductId,z => z.ProductId)
{ }
}
至于使用,你应该尽可能利用comparers。例如,不是在用作字典键的每个字符串(逻辑将散布在您的应用程序中)中调用 ToLower()
,您应该声明字典使用不区分大小写 StringComparer
。接受比较器的LINQ运算符也是如此。但同样,总是要考虑是否应该是类的内在而不是外部定义的等价行为。
I'm looking for real world best practices, how other people might have implemented solutions with complex domains.
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:
- 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
. - 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).
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)
{ }
}
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.
这篇关于使用IEqualityComparer< T>的推荐最佳做法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!