IEqualityComparer <T>和IEquatable <T>有什么区别?
我想了解应该使用IEqualityComparer<T>
和IEquatable<T>
的场景。 两个MSDN文档看起来非常相似。
IEqualityComparer<T>
是一个对象的接口,用于对T
types的两个对象执行比较。
IEquatable<T>
用于T
types的对象,以便它可以将自己与另一个对比。
当决定是否使用IEquatable<T>
或IEqualityComparer<T>
,可以问:
是否有一种testing
T
两个实例是否相等的首选方法,还是有几个同样有效的方法?
-
如果只有一种方法来testing
T
两个实例是否相等,或者有几个方法中的一个是优先的,那么IEquatable<T>
就是正确的select:这个接口应该只由T
本身实现,这样一个T
实例具有如何将自身与T
另一个实例进行比较的内部知识。 -
另一方面,如果有几个同等合理的方法比较两个
T
s是否相等,IEqualityComparer<T>
看起来更合适:这个接口并不意味着由T
本身实现,而是由其他“外部”类实现。 因此,在testingT
两个实例是否相等时,由于T
没有内部对等的理解,因此必须根据您的具体要求明确select执行testing的IEqualityComparer<T>
实例。
例:
让我们考虑这两种types(应该是有价值的语义 ):
interface IIntPoint : IEquatable<IIntPoint> { int X { get; } int Y { get; } } interface IDoublePoint // does not inherit IEquatable<IDoublePoint>; see below. { double X { get; } double Y { get; } }
为什么只有这些types之一会inheritanceIEquatable<>
,而不是其他的?
理论上,只有一种比较两种情况的明智方式:如果两种情况下的X
和Y
属性相等,则它们是相等的。 按照这个思路,这两种types都应该实现IEquatable<>
,因为似乎没有其他有意义的方法进行平等testing。
这里的问题是,由于细微的舍入错误 , 比较浮点数相等性可能无法按预期工作 。 有几种不同的方法比较近似平等的浮点数,每种方法都有特定的优点和折衷,您可能希望能够select适合自己的方法。
sealed class DoublePointNearEqualityComparerByTolerance : IEqualityComparer<IDoublePoint> { public DoublePointNearEqualityComparerByTolerance(double tolerance) { … } … public bool Equals(IDoublePoint a, IDoublePoint b) { return Math.Abs(aX - bX) <= tolerance && Math.Abs(aY - bY) <= tolerance; } … }
请注意,我链接到(上面)页面明确指出,这种testing近乎平等有一些弱点。 由于这是一个IEqualityComparer<T>
实现,所以如果对于您的目的来说不够好,您可以将其交换出来。
你已经有了它们的基本定义。 简而言之,如果在类T
上实现了IEquatable<T>
,那么IEquatable<T>
types的对象上的Equals
方法会告诉您对象本身(正在testing的是否相等)与另一个相同typesT
实例相同。 而IEqualityComparer<T>
用于testingIEqualityComparer<T>
的任何两个实例的相等性,通常在T
实例的范围之外。
至于他们是什么,可以混淆起初。 从定义中应该清楚,因此IEquatable<T>
(在T
类本身中定义)应该成为表示对象/实例唯一性的事实标准。 HashSet<T>
, Dictionary<T, U>
(考虑GetHashCode
也被重写), Contains
List<T>
等等。 在T
上实现IEqualityComparer<T>
并不能帮助上面提到的一般情况。 随后,除了IEquatable<T>
任何其他类实现IEquatable<T>
价值不大。 这个:
class MyClass : IEquatable<T>
很less有道理。
另一方面
class T : IEquatable<T> { //override ==, !=, GetHashCode and non generic Equals as well public bool Equals(T other) { //.... } }
是应该如何做的。
IEqualityComparer<T>
在需要自定义相等性validation时非常有用,但不是一般规则。 例如,在某Person
某个阶层,你可能需要根据他们的年龄来testing两个人的平等。 在这种情况下,你可以这样做:
class Person { public int Age; } class AgeEqualityTester : IEqualityComparer<Person> { public bool Equals(Person x, Person y) { return x.Age == y.Age; } public int GetHashCode(Person obj) { return obj.Age.GetHashCode; } }
要testing它们,请尝试
var people = new Person[] { new Person { age = 23 } }; Person p = new Person() { age = 23 }; print people.Contains(p); //false; print people.Contains(p, new AgeEqualityTester()); //true
同样, IEqualityComparer<T>
上的IEqualityComparer<T>
没有任何意义。
class Person : IEqualityComparer<Person>
这确实有效,但对眼睛看起来并不好,并且打败了逻辑。
通常你需要的是IEquatable<T>
。 理想情况下,您可以只有一个IEquatable<T>
而多个IEqualityComparer<T>
可能基于不同的标准。
IEqualityComparer<T>
和IEquatable<T>
完全类似于Comparer<T>
和IComparable<T>
,它们用于比较而不是等同; 这里的一个很好的线程,我写了相同的答案:)
IEqualityComparer用于当两个对象的等式是在外部实现的时候,例如,如果你想为两个没有源的types定义一个比较器,或者两个事物之间的相等只在某些有限的情况下才有意义。
IEquatable是为了实现对象本身(被比较的是相等的)。
一个比较两个T
s。 另一个可以与其他T
比较。 通常,你只需要一次使用一个,而不是两个。