首页 > 解决方案 > 如何抑制可能的空引用警告

问题描述

我正在使用 c# 8 中的可空类型,我发现了一个困扰我的问题。假设我有一个采用可为空参数的方法。当参数为空时,我想抛出一个特定的异常。但我希望该方法干净并在其他地方检查参数。check 方法抛出异常,所以方法后面的参数不能为空。不幸的是,编译器没有看到这一点并向我发出警告。这是方法:

    public void Foo(string? argument)
    {
        GuardAgainst.Null(argument, nameof(argument));
        string variable = argument; // <-- Warning CS8600  Converting null literal or possible null value to non - nullable type
        var length = argument.Length; //<--Warning CS8602  Dereference of a possibly null reference
    }

检查方法如下:

    public static void Null(string? text, string paramName)
    {
        if (text == null)
            throw new ArgumentNullException(paramName);
    }

现在,我可以抑制这样的警告:

#pragma warning disable CS8602
var length = argument.Length;
#pragma warning restore CS8602

但这有点扼杀了我保持代码清洁的意图。所以我的问题是:有没有更好的方法来抑制警告?或者也许告诉编译器从现在起参数保证不为空?

标签: c#.net-core-3.0nullable-reference-types

解决方案


这可以满足您的要求:

public static void Null<T>([NotNull] T? value, string paramName)
{
    if (value == null)
        throw new ArgumentNullException(paramName);
}

[NotNull]属性指示分析,调用此方法后,value将不会是null.

这意味着您不需要!操作员,这更清洁、更自然。

void M(string? argument)
{
    GuardAgainst.Null(argument, nameof(argument));
    string variable = argument; // no warning
    // ...
}

此处使用不受约束的泛型类型参数T意味着此方法适用于引用类型(例如string)和可空值类型(例如int?)。

如果您使用的是 .NET 6,则可以通过以下方式进一步简化此CallerArgumentExpressionAttribute操作:

public static void Null<T>(
    [NotNull] T? value,
    [CallerArgumentExpression(parameterName: "value")] string? paramName = null)
{
    if (value == null)
        throw new ArgumentNullException(paramName);
}

这样,第二个参数可以省略,调用者可以简化为:

GuardAgainst.Null(argument);

将类型上的?说明符视为两件事:1)在调用之前该值可以为 null,2)之后该值可以为 null。另一种写法是[AllowNull, MaybeNull]?在可为空的上下文中不存在同样意味着[DisallowNull, NotNull]. 就您的Null方法而言,[AllowNull, NotNull]由于NotNull.


推荐阅读