c# - 在引用类型上重写 Equals 是否应该始终意味着值相等?

标签 c# .net

在不对引用类型做任何特殊处理的情况下,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/yPersonx==y 都会给出相同的结果或 object,或者在泛型方法中确实是 T
  • 只要 EqualsGetHashCode 兼容,大多数事情都会解决,一个简单的方法是不覆盖它们

但是请注意,对于值类型,我总是建议相反的做法,即显式覆盖Equals/GetHashCode;但是,编写 struct 真的并不常见

关于c# - 在引用类型上重写 Equals 是否应该始终意味着值相等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17573720/

相关文章:

c# - 如何进行服务器端 C# SQL 验证

c# - 命名空间 'Azure' 中不存在类型或命名空间 'Microsoft' - Visual Studio 2022

.net - 使用 Moq 使用 Expression<Func<T,bool>> 参数的模拟方法

.net - 使用 TcpClient 和 Socket 伪造慢速连接

c# - 有没有所谓的私有(private)类

c# - 如何统一使用wwwform传递json

C# 无法转义正则表达式字符串中的引号

c# - 什么是NullReferenceException,如何解决?

.net - .NET 框架中的 Vector3 类

c# - xUnit - 显示理论成员数据的测试名称 (TestCase)