【问题标题】:Should == operator behave exactly as Equals()? [duplicate]== 运算符的行为是否应该与 Equals() 完全相同? [复制]
【发布时间】:2015-11-13 21:12:50
【问题描述】:

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

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

那么object.Equals()IEquatable<Polygon>.Equals() 呢? MSDN 并不暗示 ==.Equals() 应该做同样的事情,但仍然 - 它不会使 Polygon 对象的行为过于模棱两可吗?

另外,Polygon 类是可变的。

【问题讨论】:

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


【解决方案1】:

MSDN 几乎清楚了

要检查引用是否相等,请使用ReferenceEquals检查 值相等,一般应该使用Equals。但是,等于它 由Object 实现,只是执行一个引用身份检查。它 因此,当您致电Equals 时,验证是否 type 覆盖它以提供值相等语义。当你创建 你自己的类型,你应该覆盖Equals


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

IEquatable文档也很清楚

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

【讨论】:

  • 我不想覆盖==。我在问是否在可变类中覆盖.Equals()(使其按值进行比较)不会引入歧义。考虑到价值平等检查在意识形态上是参考检查的“次要”。
【解决方案2】:

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

  1. 无论你发生什么,你是否永远等同于某个特定引用所标识的对象。

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

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

我个人的建议是可变对象不覆盖 Object.Equals,而是提供一个静态属性,该属性返回一个 IEqualityComparer,用于测试值是否相等。这将要求 任何不可变地封装可变对象的对象都必须 获取IEqualityComparer 以便能够报告封装对象的 价值等价关系作为它自己的,但有一个IEqualityComparer 可以将这些东西存储在例如一个Dictionary 提供 它们永远不会被修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-10
    • 2012-12-10
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 2017-01-09
    相关资源
    最近更新 更多