Init仅引用C#10.0中启用了可为null的属性



我试图使用init only属性来强制客户端代码在创建类时初始化我的类,但没有构造函数。它没有按我的计划工作。

这是一节课,为了说明这一点,我们把它拆开。

public class Target
{
public int              Id               { get; init; }
public string           Name             { get; init; }
}

项目正在进行中。NET 6.0,所以我使用的是C#10.0。Nullable设置为"0";启用";因此引用属性Name必须为非null。让我困惑的是,编译器抱怨在构造函数之后Name属性可能为null。

CS8618:退出构造函数时,不可为null的属性"Name"必须包含非null值

当然,这是真的,但使用仅init属性的全部意义在于,我不想要构造函数。我想强制人们使用init-only属性来将Name初始化为有效的值。如果我想写一个构造函数,我可以只写一个只读属性。

(我意识到我可以自己将Name默认为string.Empty或其他有效值,但我想强制编码器这样做(

C#10.0是否为我提供了一种方法来实现我想要的而无需执行以下任何操作?

  • 将引用属性默认为某个非null值(通过构造函数或内联初始值设定项(
  • 将属性声明为可为null
  • 完全禁用null
  • 使用record类型而不是类(因为我想要成员函数(

这可行吗?

我在这个话题上的搜索让我找到了这篇文章,但我能从中得到的最好的东西是一个链接到Mads Torgensen的博客,讨论他们在C#10中的计划。它有更新吗?

init属性不强制要初始化的值,只有构造函数才强制。init所做的是,如果属性要初始化,则必须在对象初始值设定项(或构造函数,如果有(的构造时完成:它不能保证会这样做。

如果您希望在这里获得最大的健壮性,请改为通过构造函数初始化它们,这允许您添加保护子句并保证不可为null的属性。

这就是你想要的(我也这么做(:

  • 必需属性

此建议添加了一种指定在对象初始化期间需要设置属性或字段的方法,迫使实例创建者在创建站点的对象初始化器中为成员提供初始值。

这可以从使用required关键字的C#11/.net 7开始。例如:

public class Target
{
public int Id { get; init; }
public required string Name { get; init; }
}

C#11发布说明的相关部分:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required

关键字文档:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required