.NET 6 使记录中的属性必需且非空的最佳方法是啥

Posted

技术标签:

【中文标题】.NET 6 使记录中的属性必需且非空的最佳方法是啥【英文标题】:.NET 6 What is the best way to make properties required and non-null in records.NET 6 使记录中的属性必需且非空的最佳方法是什么 【发布时间】:2021-12-21 14:54:16 【问题描述】:

我搜索了它的答案,但找不到明确的答案。是的,我知道类似的问题无处不在。我希望我能在这里得到答案。

假设我有一个具有 2 个属性(FirstName、MiddleName)的 Person 类。 FirstName 是必需的,MiddleName 是可选的。

我希望FirstName 属性始终具有不可为空的数据。

以下是我想到的一些选项(但似乎没有一个是完美的)。

一种可选方法是使用记录的简短语法:

// FirstName might be null (bad)
// MiddleName is optional (good)
public record Person(string FirstName, string? MiddleName);

另一种方法是使用null-forgiving operator,但仍然是同样的问题。

// FirstName might be null (bad)
// MiddleName is optional (good)
public record Person

    public string FirstName  get; init;  = null!;

    public string? MiddleName  get; init; 

旧选项是检查构造函数中的输入:

// FirstName is required and will always have some data (good)
// MiddleName is optional (good)
// Long syntax (bad)
public record Person

    public string FirstName  get; init; 

    public string? MiddleName  get; init; 

    public Person(string firstName, string? middleName)
    
        // Probably it would be better to check if it is NullOrWhiteSpace.
        ArgumentNullException.ThrowIfNull(firstName);

        FirstName = firstName;
        MiddleName = middleName;
    

如果最后一个选项是强制非空值的方式,那么我会问:

    有了所有新的缩短语法,我们真的应该这样做吗? 什么时候应该使用缩短的记录方式? (我总是想验证必填字段是否具有值并在构造函数中进行)。

【问题讨论】:

"但仍然是同样的问题" -- 我想你从来没有说过真正的问题是什么?同样:“MiddleName 是可选的(好)”——为什么这样好? 记录不应该是所有情况下的首选解决方案。它们带有非常清晰且有限的功能集。如果你不能忍受所有这些特性,要么接受你必须编写比“基本语法”更多的代码,或者只是不使用记录开始。如果您在这些属性中必须有 值,则您的 only 选项是带有保护子句的构造函数。 目前无法混合验证和主要 ctor,e.g. see here。这意味着你基本上被一个明确的 ctor 所困。 是的,目前除了使用 if 语句或 ?? throw ... 语法的显式构造函数之外,您别无选择。 Related. 【参考方案1】:

我可能会选择在构造函数上强制执行它的经典方式。 当总是需要名字时,并没有真正看到它的缺点

【讨论】:

以上是关于.NET 6 使记录中的属性必需且非空的最佳方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

如何平均来自非空且非零的特定单元格的值?

添加具有空字符串作为默认值且非空约束的列会导致 oracle 数据库的行为不一致

列表“icons”中的每个字典都应该包含一个非空的 UTF8 字符串字段“type”

php语言判断零和空怎么判断啊?

如何使我的字符串属性可以为空?

退出构造函数时,不可为空的属性必须包含非空值。考虑将属性声明为可为空