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

本文关键字:运算符 应该 Equals | 更新日期: 2023-09-27 18:21:48

让我们考虑Polygon类。大多数情况下,检查相等性应该会比较引用,但在许多情况下,值相等会派上用场(比如用Assert.AreEqual比较两个多边形)。

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

那么object.Equals()IEquatable<Polygon>.Equals()呢?MSDN并不意味着==.Equals()应该做同样的事情,但它不会让Polygon对象的行为变得过于模糊吗?

此外,Polygon类是可变的。

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

MSDN对它的几乎是一清二楚

要检查参考相等性,请使用ReferenceEquals要检查值相等时,通常应使用Equals。然而,等于由CCD_ 12实现。它因此,当您调用Equals时,验证类型重写它以提供值相等语义。当您创建您自己的类型,您应该覆盖Equals


默认情况下,运算符==通过确定两个引用是否指示同一对象,so reference类型不需要实现运算符==即可获得功能当一个类型是不可变的时,意味着包含在实例无法更改,重载运算符==进行比较值相等而不是引用相等可能很有用,因为不可变对象,只要它们具有相同的值在非可变类型中重写运算符==是不推荐

IEquatable文档也是非常清晰的

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

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

  1. 无论你身上发生了什么,你是否永远都等同于某个特定参照物所识别的对象。

  2. 你会认为自己等同于某个特定引用所标识的对象吗?除非或直到某个引用你的东西做了会影响等效性的事情。

对于不可变对象,这两种关系都应该测试值的相等性。对于可变对象,第一个问题应该测试引用等价性,第二个问题应该检测值相等性。对于一个不可变的对象,它包含对一个可变类型的对象的引用,但它永远不会发生变异,这两个问题都应该测试封装对象的值相等性。

我个人的建议是,可变对象不要覆盖Object.Equals,而是提供一个静态属性,返回一个测试值相等的IEqualityComparer。这需要任何不可变地封装可变对象的对象都必须使IEqualityComparer能够报告封装对象的值等价关系,但具有IEqualityComparer将使得可以将这些东西存储在例如提供的CCD_ 22中它们从不被修改。