未密封的类型不应该实现IEquatable<T>
,因为确保(甚至可能)派生类型正确实现它的唯一方法是实现IEquatable<T>.Equals(T)
以调用Object.Equals(Object)
. 由于 的全部目的IEquatable<T>
是避免Object
在比较它们之前浪费 CPU 时间来转换事物,因此调用的实现Object.Equals(Object)
无法比未实现接口时实现的默认行为更快地执行任何操作。
密封类类型可以通过实现来获得轻微的性能优势IEquatable<T>
;首选样式是Object.Equals(Object)
尝试将参数转换为T
; 如果转换成功,则使用IEquatable<T>.Equals
实现;否则返回false
。在传递相同的对象实例时,在任何情况下都不应产生不同的IEquatable.Equals(T)
结果。Object.Equals(Object)
结构类型可以使用与密封类类型相同的模式。尝试转换的方法有点不同,因为失败的转换不能返回null
,但模式应该仍然相同。如果一个结构实现了一个变异接口(例如List<T>.Enumerator
,一个实现 的结构IEnumerator<T>
),相等比较的正确行为有点模糊。
请注意,顺便说一句,IComparable<T>
应该IEquatable<T>
被认为是相互独立的。虽然经常会出现 when X.CompareTo(Y)
is 0X.Equals(Y)
会返回 true 的情况,但某些类型可能具有自然排序,其中两个事物可能不同,而没有一个关于另一个事物的排名。例如,一个人可能有一种NamedThing<T>
结合了 astring
和 a的类型T
。这种类型将支持 name 的自然排序,但不一定支持T
. 两个名称匹配但T
不同的实例应该返回0
for CompareTo
,但是false
for Equals
。因此,如果未更改,则覆盖IComparable
不需要覆盖。GetHashCode
Equals