如何抑制可能的空引用警告
How to suppress Possible Null Reference warnings
我正在使用 c# 8 中的可空类型,我发现了一个困扰我的问题。
假设我有一个采用可为空参数的方法。当参数为空时,我想抛出一个特定的异常。但我希望该方法是干净的,并在其他地方检查参数。 check方法抛出异常,所以方法后的参数不能为null。
不幸的是,编译器没有看到这一点并向我发出警告。
方法如下:
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
但这有点扼杀了我保持代码清洁的意图。
所以我的问题是:有没有更好的方法来抑制警告?或者告诉编译器从现在开始保证参数不为空?
好的,看起来有一个非常简单的解决方案 - the ! operator
守卫后必须使用一次,然后才认为不为空:
public void Foo(string? argument)
{
GuardAgainst.Null(argument, nameof(argument));
var length = argument!.Length;
}
这就是你想要的:
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
方法,由于 NotNull
.
的手动规范,我们最终得到 [AllowNull, NotNull]
考虑使用 null 合并运算符的解决方案 ??
The null-coalescing operator ?? returns the value of its left-hand
operand if it isn't null; otherwise, it evaluates the right-hand
operand and returns its result. The ?? operator doesn't evaluate its
right-hand operand if the left-hand operand evaluates to non-null.
public void Foo(string? argument)
{
string variable = argument ?? throw new ArgumentNullException(nameof(argument));
var length = argument.Length;
}
我认为此解决方案更简洁。您避免检查 GuardAgainst class 和 .Null() 静态方法实现细节。
我正在使用 c# 8 中的可空类型,我发现了一个困扰我的问题。 假设我有一个采用可为空参数的方法。当参数为空时,我想抛出一个特定的异常。但我希望该方法是干净的,并在其他地方检查参数。 check方法抛出异常,所以方法后的参数不能为null。 不幸的是,编译器没有看到这一点并向我发出警告。 方法如下:
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
但这有点扼杀了我保持代码清洁的意图。 所以我的问题是:有没有更好的方法来抑制警告?或者告诉编译器从现在开始保证参数不为空?
好的,看起来有一个非常简单的解决方案 - the ! operator 守卫后必须使用一次,然后才认为不为空:
public void Foo(string? argument)
{
GuardAgainst.Null(argument, nameof(argument));
var length = argument!.Length;
}
这就是你想要的:
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
方法,由于 NotNull
.
[AllowNull, NotNull]
考虑使用 null 合并运算符的解决方案 ??
The null-coalescing operator ?? returns the value of its left-hand operand if it isn't null; otherwise, it evaluates the right-hand operand and returns its result. The ?? operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
public void Foo(string? argument)
{
string variable = argument ?? throw new ArgumentNullException(nameof(argument));
var length = argument.Length;
}
我认为此解决方案更简洁。您避免检查 GuardAgainst class 和 .Null() 静态方法实现细节。