新的 c# 可空选项

New c# nullable option

在新版本的 C# 中,默认选项可为 nullable。我是说这个

这对我来说真是个好功能。但是我不明白一件事。 属性 可以由我还是由程序为空?

我知道这个 属性 永远不应该为空,因为我在表格中填写它并且从未将其设置为空。但通常它可以为空。应该怎么标注?

示例:

用户模型:

public string? Name { get; set; }

public string Name { get; set; } = null!

我真的很困惑。

如果值可以为空,并且 <Nullable>enable</Nullable> 值在您的 *.csproj 文件中设置, 必须将这些值声明为可为空。

在您给出的示例中,可空类型(而不是将 null 分配为默认值)是可行的方法:

public string? Name {get; set;}

您还会注意到 VS 会在您每次引入 属性 等可以为空但未标记为空的内容时向您发出警告。

I know that this property should never be null because I fill it in the form and never set it as null. But in general it can be null. How should I mark it?

如果在构造函数中将其设置为 non-null,那么您可以将其声明为 string 而不是 string?,因为它确实保证永远不会为 null。

但是,如果它在构造函数具有 运行 之后(并且在调用任何其他方法之前)为空,则它可以为空,您应该将其声明为 string?.

你面临的二分法是(根据你所说的)当正确使用 class 时它永远不应该为 null - 即如果调用代码确实调用了初始化 [=55= 的方法] 到 non-null 在访问它之前,它将保证不为 null - 这意味着你想将它声明为 non-null string 这样调用者就不需要使用null-forgiving ! 运算符抑制可为 null 的警告。

遇到这种情况怎么办?那么我认为你有三种可能性:

  1. 将 属性 声明为可为 null:string? 并让调用者抑制可为 null 的警告或检查该值是否为 null。
  2. 将 属性 初始化为 non-null 默认值,例如 string.Empty 并将 属性 声明为不可空 string.
  3. 假设在 属性 为 null 时访问它是一个编程错误,并抛出适当的异常。

对于最后一种情况,您可以这样做:

private string? _name;

public string Name 
{ 
    get
    {
        if (_name == null)
            throw new InvalidOperationException("Do not access Name without setting it to non-null or calling Init()");
            
        return _name;
    }   
    
    set
    {
        if (value == null)
            throw new ArgumentNullException("value", "You cannot set Name to null.");
            
        _name = value;
    }
}

这里假定有一个名为 Init() 的方法可以调用它来初始化 Name,当然您的代码可能会有所不同。

无论您采用哪种方法,您都应该真正检查 属性 setter 中的空值,如上所示。

请注意,编写 setter 空检查的更简洁的方法是:

set
{
    _name = value ?? throw new ArgumentNullException("value", "You cannot set Name to null.");
}