【问题标题】:What does .NET's Equals method really mean?.NET 的 Equals 方法的真正含义是什么?
【发布时间】:2018-10-23 14:30:44
【问题描述】:

我们知道所有类型都从其基类 Object 继承 Equals。

根据 Microsoft 文档:

只有当被比较的项目引用内存中的相同项目时,Equals 才会返回 true。

所以我们使用 Equals() 来比较对象引用,而不是对象的状态。

通常,仅当被比较的对象具有相同的内部状态值时,此方法才会被覆盖以返回 true。

我的问题:两个对象可以指向内存中的同一个项目但具有不同的状态吗?如果不是,为什么要覆盖 Equals?


感谢您提供明确的答案。对于未来的读者,这里是我们为什么覆盖的示例:

Employee A=New Employee();
Employee B=New Employee();

在这种情况下,A 和 B 始终指向不同的内存,因此 Equals 始终为 false。

但是如果:

A.SSN=B.SSN;
A.LiceneNumber=B.LiceneNumber;

这两个员工是同一个人,在这种情况下,我们需要检查状态并因此覆盖 Equals。

所以在我的例子中,问题的重点是:有可能两个不同的对象存储在两个不同的位置,但仍然引用同一个实体(在我的例子中是 Employee)。

【问题讨论】:

  • 您重写 equals 以提供更包容的平等定义,而不是更排他的平等定义。
  • Equals 不仅比较参考。 2 个整数具有不同的引用,但在比较值时返回 true 到 equals。等于都是独立实现的。通常人们会检查相同的引用,如果是则返回 true,否则他们经常逐个检查属性。
  • @Franck 是 Equals() 的一个版本,已经被 int 类型重载。从 Object 继承的 Equals() 的基本版本只比较引用。
  • @Franck 两个int 值没有不同的引用,因为它是一个值类型。只有当它们首先通过转换为object 进行装箱,然后像乔尔所说的那样,它将使用覆盖的Equals,这才是正确的。

标签: c# .net


【解决方案1】:

两个对象可以指向内存中的同一个项目但具有不同的状态吗?

这误解了对象与变量或引用之间的区别。 “内存中的项目”是对象,它所说的“状态”是用于保存对象的内存。您使用变量引用对象。提出这个问题的正确方法如下(区别确实很重要,因为它是理解 C# 和类似语言如何工作的关键):

两个变量可以引用内存中的同一个对象但状态不同吗?

要回答这个问题,您可以让两个变量引用内存中的同一个对象……但它确实是同一个对象。内存中只有一项(即对象),这意味着只有一种状态。

但这给我们带来了这个问题:

为什么要覆盖 Equals?

您重写Equals() 方法是因为有时您有两个变量引用两个不同的对象,而这两个对象具有相同的值。例如,我可以像这样创建两个字符串对象:

string a = "hello world";
string b = "hello world";

暂时忽略字符串实习,这两个变量引用内存中的两个不同的字符串对象。从Object 继承的基本Equals() 实现将导致false,但字符串类型重载Equals() 方法以进行值比较,因此a.Equals(b) 将导致true

最后,我们知道的足以回答这个问题:

存储在两个不同位置的两个不同对象是否仍然可以引用同一个实体?

是的,是的。这也是我们重载Equals() 方法(以及GetHashCode())的原因。从Object 继承的基本Equals() 方法会将它们视为两个不同的对象,结果将是false。您为该类型覆盖 Equals(),以便当两个对象表示相同的值时,它可以返回 true

现在开始变得棘手了。一个应用程序可能以 同一个人 的两个 Employee 类型实例结束,然后用户只更改其中一个的电子邮件地址属性。现在你有两个实例。对于同一个员工。 有些字段有不同的值。

你想让Equals()做什么?仔细考虑一下;多年来,它一直是许多应用程序中许多错误的根源。有时你需要一种方式。有时你需要另一个。有时,行为需要根据同一应用程序中的上下文进行更改。

【讨论】:

    【解决方案2】:

    2个[变量]可以指向内存中的同一个项目但有不同的状态吗?

    没有。

    如果不是,为什么要覆盖 Equals?

    更改比较引用相等的默认行为,比较对象的值。

    另见When Should a .NET Class Override Equals()? When Should it Not?

    【讨论】:

      【解决方案3】:

      您覆盖 equals 以便您可以测试内存中不同项目的对象的相等性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-06
        • 2012-03-30
        • 2011-10-10
        • 2012-08-03
        • 2012-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多