【发布时间】:2013-07-10 14:44:05
【问题描述】:
如果不对引用类型做任何特殊处理,Equals() 将意味着引用相等(即相同的对象)。如果我选择为引用类型覆盖Equals(),是否总是意味着两个对象的值是等价的?
考虑这个可变的Person 类:
class Person
{
readonly int Id;
string FirstName { get; set; }
string LastName { get; set; }
string Address { get; set; }
// ...
}
代表完全相同的人的两个对象将始终具有相同的Id,但其他字段可能会随着时间的推移而不同(即在地址更改之前/之后)。
对于这个对象,Equals 可以定义为不同的东西:
- 值相等:所有字段都相等(代表同一个人但地址不同的两个对象将返回 false)
- 身份平等:
Ids相等(代表同一个人但地址不同的两个对象将返回 true) - 引用相等:即不实现 Equals。
问题:哪些(如果有)更适合这个课程? (或者问题应该是,“这个类的大多数客户期望 Equals() 表现如何?”)
注意事项:
- 使用值相等使得在
Hashset或Dictionary中使用此类变得更加困难 -
使用 Identity Equality 使 Equals 和
=运算符之间的关系变得奇怪(即在检查两个 Person 对象(p1 和 p2)后,Equals()返回 true,您可能仍想更新您的引用以指向“较新”的 Person 对象,因为它不是等价的)。例如,下面的代码读起来很奇怪——看起来它什么都不做,但实际上是删除 p1 并添加 p2:HashSet<Person> people = new HashSet<Person>(); people.Add(p1); // ... p2 is an new object that has the same Id as p1 but different Address people.Remove(p2); people.Add(p2);
相关问题:
【问题讨论】:
-
在等式有多种含义的情况下,为什么不提供
IEqualityComparer(T)的一些实现,让消费者选择使用哪个等式呢? -
@Romoku,看起来很合理,然后我认为这意味着您根本不会实现
.Equals()? -
我认为 Marc Gravell 的回答解决了这个问题。
-
如果代表完全相同的人的两个对象总是具有相同的
Id,那么我希望Equals只比较Id字段。对于Equals方法,其他任何东西都没有意义,并且如果您要比较可变字段,则可能会很危险。 -
@JimMischel,“其他任何事情对 Equals 来说都没有意义”,为什么不呢?我给出了
Equals的三种含义(每种含义都可能对客户有用)。