【问题标题】:Equals override and == overload, for value objects vs entities等于覆盖和 == 重载,用于值对象与实体
【发布时间】:2016-05-31 06:13:29
【问题描述】:

我发现了很多关于 Equals 覆盖和 == 运算符重载之间差异的讨论,但是对于何时应该或不应该覆盖默认的相等行为似乎存在一些分歧,这让我怀疑这样做的好方法。

以下是我的理解,如果您觉得有问题,请告诉我:

1) == 不建议对非不可变类型进行重载(为什么?参考文献。

2) 等式(和 GetHashCode)也应该在不可变类型中被覆盖,以便对类型内相关字段的每个值进行良好的比较。

3) 实体的 Equals 怎么样?

重写 Equals 并仅比较 id 属性是个好主意吗?还是应该让默认的对象行为比较引用?

对于这两个选项,我认为如果我遵循在线程上下文中始终只有一个特定实体的一个实例的规则,结果应该是相同的,但是其中一个是否有一些缺点或优点我应该注意这些选项?

【问题讨论】:

  • 在处理集合时,平等问题是最重要的。

标签: c# domain-driven-design equality


【解决方案1】:

动机

在我看来,正确的相等运算是面向对象世界中最被低估的工具之一。是的,您绝对应该在有意义的地方实现它们,这将使您的程序更加简洁。

例如比较

Assert.Equal(expectedAddress.Street, address.Street);
Assert.Equal(expectedAddress.City, address.City);
Assert.Equal(expectedAddress.Zip, address.Zip);
Assert.Equal(expectedAddress.State, address.State);
Assert.Equal(expectedAddress.Country, address.Country);

Assert.Equal(expectedAddress, address);

当您有深度嵌套的值对象时,这会变得更加极端。

何时使用

为了不产生尴尬的行为,只对不可变类型实现相等操作。这很重要,因为例如哈希映射无法在可变类型中正常工作(想想当对象的哈希码在哈希映射中发生变化时会发生什么)。

单独实现 Equals 对于某些可变类型可能有意义,但通常不鼓励使用,例如通过Microsoft code analysis rule

值对象

等式运算在值对象上最有用。还要覆盖等式运算符,使等式比较看起来更自然。

等式运算的实现很简单:考虑所有数据字段,但忽略计算属性。这将创建纯粹基于内容的相等操作。

由于在值对象上实现相等操作是机械的,所以有一个 library called Equ 会自动为您执行此操作(这是我自己编写的)。它将在静态实例化时创建相等操作,其运行时性能与手动编写的 EqualsGetHashCode 实现相同。

实体

对于实体,它变得有点棘手。问题在于,从领域的角度来看,平等的含义通常不是很清楚。

显然,两个 ID 不同的Customer 实体并不相等。但仅此而已。具有相同 ID 但处于不同状态的两个 Customer 实体是否相等?难题。

好消息是这种功能并不是真正需要的。所以我的建议是:不要对实体执行相等操作。

【讨论】:

  • 很好的解释谢谢,我说得对吗,如果我们使用 struct c# 将为我们完成这项工作并自动执行值相等,所以我们不需要实现它?
  • 另外,到目前为止(但我并不太远;))我发现 ddd 值对象似乎很自然地适合 c# struct 实现,对每个值都使用 struct 是个好主意对象?复杂的可能有一些例外......
  • 结构体只适用于最小的值对象。我通常将 VO 设计为类,除非我有非常具体的理由不这样做。
猜你喜欢
  • 2016-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
  • 2012-02-26
相关资源
最近更新 更多