.NET的Equals方法到底意味着什么?

时间:2018-10-23 14:30:44

标签: c# .net

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

每个Microsoft文档:

  

Equals仅在要比较的项目引用内存中的同一项目时才返回true。

因此,我们使用Equals()比较对象引用,而不是对象状态。

  

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

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


感谢您提供清晰的答案。对于将来的读者,这是我们为何覆盖的示例:

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

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

但是,如果:

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

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

因此,在我的情况下,问题的关键是:两个不同的对象可能存储在两个不同的位置,但仍引用同一实体(在我的情况下为Employee)。

3 个答案:

答案 0 :(得分:12)

  

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

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

  

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

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

但这使我们想到了这个问题:

  

为什么要覆盖等于?

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

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

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

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

  

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

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

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

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

答案 1 :(得分:4)

  

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

否。

  

如果不是为什么要覆盖等于?

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

另请参阅When Should a .NET Class Override Equals()? When Should it Not?

答案 2 :(得分:2)

您可以覆盖等于,因此可以测试内存中不是同一项目的对象是否相等。