在不对引用类型做任何特殊处理的情况下,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() 表现如何?”)
注意事项:
- 使用值平等使得在
Hashset
中使用此类变得更加困难或Dictionary
使用恒等式建立 Equals 和
=
之间的关系operator strange (即在检查两个 Person 对象(p1 和 p2)后返回 true 为Equals()
,您可能仍想更新您的引用以指向“较新的”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);
相关问题:
最佳答案
是的,为此确定正确的规则很棘手。这里没有单一的“正确”答案,这在很大程度上取决于上下文和偏好就个人而言,我很少考虑太多,只是默认在大多数常规 POCO 类上引用相等性:
- 在哈希集中使用
Person
作为字典键/的情况很少- 当你这样做时,你可以提供一个自定义比较器,它遵循你希望它遵循的实际规则
- 但大多数时候,我会简单地使用
int Id
作为字典(等)中的键 无论如何
- 使用引用相等意味着无论
x
/y
是Person
,x==y
都会给出相同的结果或object
,或者在泛型方法中确实是T
- 只要
Equals
和GetHashCode
兼容,大多数事情都会解决,一个简单的方法是不覆盖它们
但是请注意,对于值类型,我总是建议相反的做法,即显式覆盖Equals
/GetHashCode
;但是,编写 struct
真的并不常见
关于c# - 在引用类型上重写 Equals 是否应该始终意味着值相等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17573720/