我无法解决一个难题。
-
如果我将
ValueObjects
建模为c#records
,我最终会因为with {Property = something}
而出现问题,因为在这种情况下,自动生成的init
属性可能会绕过构造函数中强制执行的一些逻辑,例如 -
如果我将它们建模为常规类,那么我必须检查在将它们用作参数的构造函数/方法中它们是否为null。
-
如果我将它们建模为
struct
(我倾向于大多数atm(,那么我没有空检查,但仍然有默认值检查(如果实体不允许(。 -
我能想到的最后一个选项是将它们建模为
struct
,其中私有isValid
属性最初设置为false
,在我的构造函数中设置为true
,并在getters中签入。
我是否缺少任何其他选项,这些选项有望使使用VO的构造函数/方法中的null检查变得不必要,同时又是真正不可变的?
[更新]
一个例子:
public LegalSubject(LegalSubjectId id,
GeneralInfo generalInfo,
VatId vatId,
LegalSubjectId? customerId
{
// LegalSubjectId cannot be null
// GeneralInfo cannot be null
// VatId cannot be null
}
现在,每个值对象(例如GeneralInfo
(的属性都在创建时进行检查。因此,例如,它强制要求GeneralInfo.Name
不为空,GeneralInfo.Email
不为空等等…(显然,struct
在这里不适用,因为默认值会使VO处于无效状态(。
在这个使用VO的类中,最好有一种方法来避免null检查/默认检查。struct
和isValid
(在非默认构造函数中设置(解决了这个问题,但我希望还有其他我缺少的解决方案。
PS。如果强制执行可为null的引用类型(而不仅仅是警告(,这将解决问题。但事实并非如此。
就我所了解的值对象而言,您不应该拥有无效的值对象。它们应该始终有效且不可变。
因此,除了检查所有参数是否有效的构造函数(或工厂方法(之外,没有其他选择了。你似乎非常关注null,你确定这是你能得到的唯一无效数据吗?
如果您唯一关心的是null值,那么您可能希望研究可为null的引用类型,这可能会使其更容易。
但最终,是的,一个带有构造函数的常规类会检查输入的有效性,以构建一个有效的、不可变的对象,这就是构建值对象的方式。