C# 9.0 记录 - 非空引用类型和构造函数

9

我尝试了一个简单的记录:

#nullable enable

public record Product
{
    public readonly string Name;
    public readonly int CategoryId;
    public readonly string Phone;
    public readonly Address Address;
    public readonly Manager Manager;
}

我收到了警告:

非空属性“Name”未初始化。考虑将该属性声明为可为空。

(CategoryId 除外,所有字段都是如此)

基本上,如果我理解正确,编译器不会自动生成接受和设置所有字段的构造函数(当使用 #nullable enable 时),我必须自己编写,即:

public Product(string Name, int CategoryId, string Phone, Address Address, Manager Manager) {
  this.Name=Name;
  this.CategoryId=CategoryId;
   ...
}

我的问题是,这正确吗?我对此感到非常惊讶,因为我认为整个重点是使创建这样的记录变得非常简单,并且编写/维护构造函数非常繁琐,尤其是在经常更改的大型记录上。

或者我错过了什么?


5
为什么不将它们适当地声明为init属性,而不是公共只读字段? - Camilo Terevinto
1
@CamiloTerevinto 使用初始化属性不会改变警告。 - kofifus
1
@juergend 移除 readonly 不会改变警告。 - kofifus
2
我认为你不需要手动生成构造函数(但我可能错了),但即使在这种情况下,你仍然可以使用new Product(),这样你仍然可能会得到未初始化的成员变量。至少对于9.0版本,如果你想要#nullable enable,你仍然需要继续编写构造函数。 - Camilo Terevinto
是的,这就是为什么在这种情况下我预期没有默认构造函数,只有像我手动编写的那样的构造函数.. 我真的很惊讶它不是这样的。 - kofifus
显示剩余4条评论
1个回答

3
您似乎期望使用自动生成的 主要构造函数,但是只有在记录类型声明中使用记录参数时,才会自动生成它(并且通常情况下,您将获得所有记录优点),这些记录参数会自动映射到getinit 属性,并且会从主要构造函数进行自动初始化,因此消除了 NRT 警告。
这意味着,您可以通过基本使用常规构造函数语法,并添加 record 关键字,获取所有记录类型的特性。
public record Product(string Name, int CategoryId, string Phone, Address Address, Manager Manager) { }

我看到了,如果我尝试这个 - 请参见 https://sharplab.io/#gist:830bc1e956d87308c739e9b943aeef1a - 属性有 { get; set; } 而不是 { get; init; } - kofifus
3
我写的是“规范”(spec),我们实际得到的是当前的“预览版”(preview implementation)。这就是为什么我通常反对测试/讨论预览版,因为它们可能与发布时得到的东西差别很大。记录类型的整个想法是将它们作为匿名类型的类型化变体。显然,在这方面还有更多的工作要做 :) - Ivan Stoev
2
但是我已经在最新的预览版VS2019中尝试过了,即使对象浏览器显示它们为“get; set;”,编译器也不允许从外部设置它们,因此可能只是缺少“init”元数据。 - Ivan Stoev
对于那些想知道“_Primary Constructor_”是什么意思的人,这里有解释 - https://www.infoq.com/news/2020/01/CSharp-Primary-Constructors/ - Alex Klaus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接