使用NotNull属性有什么意义?

3

我知道从C# 8开始,默认情况下引用类型是非空的,我们可以在项目文件中打开NRT。我看到了像这样的代码:

static void ThrowIfNull([NotNull] string? x)
{
    if (x == null)
    {
        throw new ArgumentNullException();
    }
}

我不知道在参数中使用[NotNull]有什么意义。这就像告诉编译器:

"如果方法返回而没有抛出异常,那么x保证永远不会是null"

但是编译器为什么需要这个信息呢?如果我们这样做:

static void ThrowIfNull(string? x)
{
    if (x == null)
    {
        throw new ArgumentNullException();
    }
}

由于我们进行了空指针检查,所以代码没有产生警告。


这个主题似乎相当复杂。你已经阅读了《由C#编译器解释的空状态静态分析属性》吗?(我还没有仔细阅读,但乍一看它可能会为你提供一些答案。) - Bart Hofland
2个回答

2
属性是方法的调用者。 C#编译器会在当前方法和被调用方法的签名中限制可空性分析的范围。
换句话说,如果调用方法看起来像这样:
static void Caller()
{
  string? str = GetString();
  ThrowIfNull(str);
  Console.WriteLine(str.ToUpper());
}

应该有一个编译器警告,即.ToUpper()可能会出现NRE。

然而,如果您装饰属性,编译器将知道ThrowIfNull方法的正常返回意味着str不为null,警告应该被修复。

传播这些信息的另一种替代方式是使ThrowIfNull()在字符串不为null时返回该字符串。然后,您可以这样做:

static void Caller()
{
  string? str = GetString();
  var str2 = ThrowIfNull(str);
  Console.WriteLine(str2.ToUpper());
}

0
当使用?语法声明可空性(且启用了可空性注释)时,不应使用[NotNull],因为实际上它是相同的,或者在您的情况下是矛盾的。要么字符串不为空(那么您不需要?),要么它可以为空,那么添加?但不需要[NotNull]属性。当启用nullability注释时,NotNull-Attribute已被弃用,因为编译器基于问号说明符的使用实际上会在内部执行相同的操作。
有一些属性可能仍然需要使用,例如[NotNullWhen()],但除此之外,请勿混合使用Nullability属性和nullability注释。

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