应该==运算符的行为与Equals()完全相同吗?

时间:2015-11-13 21:12:50

标签: c# .net operator-overloading equals iequatable

让我们考虑Polygon课程。检查是否相等应该在大多数时间比较引用,但是在很多情况下值相等都很方便(比如将两个多边形与Assert.AreEqual进行比较时)。

我的想法是让价值平等在某种程度上继承参考平等。在这种情况下,==operator应该保留其默认的引用检查实现非常明显。

那么object.Equals()IEquatable<Polygon>.Equals()呢? MSDN并不意味着==.Equals()应该这样做,但仍然不会使Polygon个对象的行为过于模糊?

此外,Polygon类是可变的。

2 个答案:

答案 0 :(得分:2)

MSDN几乎可以清楚

  

要检查参考相等性,请使用ReferenceEquals要检查   值相等,通常应使用Equals 。但是,等于它   由Object实现只执行引用标识检查。它   因此,当您致电Equals时,确认是否重要   type会覆盖它以提供值相等语义。当你创建   您自己的类型,您应该覆盖Equals

  

默认情况下,运算符==测试引用相等性   确定两个引用是否表示相同的对象,所以引用   类型不需要实现operator == 以获得此功能   功能。 当类型是不可变的时,表示包含的数据   实例无法更改,重载operator ==进行比较   值相等而不是引用相等可能很有用因为,as   不可变对象,只要它们可以被认为是相同的   具有相同的价值。 在非不可变类型中覆盖运算符==   不推荐

IEquatable文档也很清楚

  

定义值类型或类实现的通用方法   创建一个特定于类型的方法来确定实例的相等性

答案 1 :(得分:1)

在.NET(以及Java)中进行相等性测试的一个主要困难是,有两个有用的等价关系,每个都基于一个可以明智地询问任何类对象的问题,但.NET并不是一致的关于应由EqualsGetHashCode应该回答的问题或关系。问题是:

  1. 无论遇到什么情况,您是否会永远等同于某个特定参考所标识的对象。

  2. 您是否认为自己等同于某个特定参考所标识的对象,除非或直到引用您的某些内容会影响该等效性。

  3. 对于不可变对象,两个关系都应该测试值相等。对于可变对象,第一个问题应该测试引用等价,第二个问题应该测试值相等。对于一个不可变对象,它持有对一个可变类型的对象的引用,但没有人会变异,这两个问题都应该测试该封装对象的值相等。

    我个人的建议是,可变对象不会覆盖Object.Equals,但是它们提供了一个静态属性,它返回一个IEqualityComparer来测试值的相等性。这需要这样做 任何不可避免地封装可变对象的对象都必须这样做 让IEqualityComparer能够报告封装的对象 价值等价关系本身,但有一个IEqualityComparer 可以将这些东西存储在例如提供了Dictionary 它们永远不会被修改。