验证使用仅 init-only setter 初始化的 C# 对象

Jac*_*ski 6 c# initialization immutability c#-9.0


重新开放的免责声明

这个问题是关于在构造过程中使用 C# 9仅初始化设置器而不是使用具有详细“样板代码”的构造函数)对不可变对象进行对象验证


C# 9 引入了一个选项,可以使用对象初始值设定项语法来初始化不可变对象,仅使用 init setter:

class Immutable
{
   public string Name { get; init; }
   public int Value { get; init; }
}

Immutable o = new Immutable { Name = "Value1", Value = 257 };
Run Code Online (Sandbox Code Playgroud)

此外,它还引入了一种很好的语法来创建对象的变异副本:

var o1 = o with { Value = 65537 };
Run Code Online (Sandbox Code Playgroud)

以前,创建和初始化新的不可变对象的唯一选择是使用带参数的构造函数。新选项更加自然和优雅,但缺少构造函数初始化的一个重要功能:验证。使用构造函数,我可以确保永远不会创建具有无效状态的对象。

可以将验证代码放入 init setter 中,但据我所知,没有办法提供对整个对象状态的一般验证。具体来说,我没有看到任何方法可以确保在上面的示例中该Name属性将履行其契约以具有非空值。由于无参数构造函数是使用对象初始值设定项语法所必需的,因此可以创建未初始化的实例:

var o = new Immutable();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,属性将获得默认值。

问题[编辑]:在使用 init setter 初始化完成后,是否有任何方法可以验证不可变对象状态?请记住,初始化语句中可能未指定属性分配,并且默认对象状态可能无效。

Jac*_*ski 1

我终于在Mads Torgersen 的 C# 9 帖子下的评论中找到了有关验证的信息。他们正在研究在 C# 10 中引入此功能的选项。

[编辑] 如果最终(至少部分)通过引入required关键字在 C# 11 中解决,该关键字可用于属性。这是非常优雅的解决方案,因为它强制在源代码级别进行分配(IDE 会突出显示缺少的分配)。尽管如此,在完成所有分配后运行一些代码的能力还是很有用的。