对于值对象与实体,等于覆盖和==重载

Jon*_*han 2 c# domain-driven-design equality

我发现很多关于Equals重写和==运算符重载之间差异的讨论,但似乎有一些关于我们应该或不重写默认的相等行为的问题,这让我怀疑这样做的好方法.

以下是我的理解,请告诉我你是否有些不对劲:

1)==不推荐非不可变类型的重载(为什么??),并且对于不可变类型(也就是DDD的值对象)非常有用,如果值相同但不是引用,则== comparaison返回true.

2)等于(和GetHashCode)也应在不变类型重写来执行类型内的相关字段的每个值的良好comparaison.

3)实体平等如何?

覆盖Equals并仅比较id属性是一个好主意吗?或者我应该让比较引用的默认对象行为?

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

the*_*Dmi 6

动机

在我看来,适当的平等操作是面向对象世界中最被低估的工具之一.是的,你应该在有意义的地方完全实现它们,它会使你的程序更加简洁.

比较

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);
Run Code Online (Sandbox Code Playgroud)

Assert.Equal(expectedAddress, address);
Run Code Online (Sandbox Code Playgroud)

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

何时使用

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

Equals单独实现可能对某些可变类型有意义,但通常不鼓励,例如通过Microsoft代码分析规则.

价值对象

平等操作对价值对象最有用.还重写相等运算符以使相等比较看起来很自然.

平等操作的实现是微不足道的:考虑所有数据字段但忽略计算属性.这将创建纯粹基于内容的平等操作.

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

实体

对于实体,它会变得有点棘手.问题在于,从域的角度来看,通常并不十分清楚平等意味着什么.

显然,Customer具有不同ID的两个实体不相等.但那是关于它的.两个Customer实体具有相同的ID,但处于不同的状态?困难的问题.

好消息是这种功能并不是真正需要的.所以我的建议是:不要对实体实现平等操作.