我们知道所有类型都从其基类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)。 >
答案 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)
您可以覆盖等于,因此可以测试内存中不是同一项目的对象是否相等。