了解IEquatable

leo*_*ora 52 c# iequatable

当我使用IEquatable<T>接口实现我想要比较的对象时:

  1. Equals(object)如果我已经实现了,为什么必须覆盖方法Equals(T)
  2. 我实施后可以使用==!=运营商IEquatable<T>吗?

Ray*_*sen 52

  1. 来自MS Docs的文章IEquatable<T>:

    如果实现了IEquatable<T>,你也应该重写的基类的实现 Equals(Object),并 GetHashCode()让他们的行为与该一致的 Equals(T) 方法.如果覆盖 Equals(Object),则在调用类上的静态Equals(Object, Object) 方法时也会调用重写的实现 .此外,您应该重载op_Equalityop_Inequality运算符.这可确保所有相等测试都返回一致的结果.

  2. 不,运营商不使用Equals方法.它们必须单独超载才能这样做.

  • 轻微的术语修正 - 你不能*覆盖*操作符,但你可以*重载*它们. (13认同)
  • 不,为此目的使用ReferenceEquals().等号运算符(==)通常意味着相同,但可以覆盖(例如对于字符串等). (8认同)
  • 是的,您可以重载==和!= in并将它们与IEquatable接口结合使用.但这需要手动完成,IEquatable不会自动完成.答案的第2部分中的"否"实际上是不正确的.注意:尝试编辑答案,但显然有些人认为评分最高的答案不正确并不足以批准更正编辑. (2认同)

Jon*_*eet 43

1)正如Ray所说,覆盖Equals(object)以确保从不知道(静态)实现的类调用方法时的一致性IEquatable<T>.例如,非泛型集合类将Equals(object)用于比较.你也应该覆盖GetHashCode().

2)实现IEquatable<T>不会自动重载==和!=运算符,但没有什么可以阻止你这样做,就像System.String那样.但是,如果你这样做,你应该非常清楚地记录这一点 - 当你在仍然使用身份比较的其他类型的引用(例如MyType和Object)之间进行比较时要小心.我怀疑这样做并不是一个好主意,除非它在你的代码中是一个非常频繁使用的类型,每个人都会非常熟悉它,并且重载的语法糖= =将真正对可读性产生积极影响.

  • 它会避免铸造,是的.对于值类型,它也将避免装箱和拆箱.请参阅Collection <T>的文档.Contains - 它使用EqualityComparer <T> .Default,如果可能,它将使用IEquatable <T>实现. (7认同)
  • 是的,重载operator ==和!=以提供值相等性检查(与默认引用相等性检查相比)不是一个好主意.MSDN文档建议您只对不可变类型执行此操作.还存在涉及接口和运算符重载的问题. (6认同)