C# 8 使用实用方法验证参数

C# 8 validate arguments with utility method

假设我有一个接受 nullable reference type 的方法,例如:

int Func(string? param)
{
    return param.Length;
}

编译器正确地警告说 param 应该检查 null

在 C# 8 之前,我习惯于使用这样的外部实用函数来验证参数:

public static class Validate
{
   public static void NotNull(object? value, string parameterName, string? field = null)
   {
     if (value == null) throw new ArgumentNullException(parameterName + (field == null ? string.Empty : "." + field));
   }
}
… 
int Func(string? param)
{
    Validate.NotNull(param, nameof(param));
    return param.Length;
}

在这种情况下,编译器似乎无法检测到参数 param 实际上在 Validate 方法内部检查了 null,因此仍然会报错。

没有其他方法可以直接测试方法内部的 null 值吗?

int Func(string? param)
{
    if (value == null) throw new ArgumentNullException(nameof(param));
    return param.Length;
}

我经常使用的一种方法听起来像你正在寻找的是这样的:

public static T MaybeThrow<T>(
   this T? pObject,
   string? pMaybeErrorMessage = null
) where T : class {
   if (pObject == null)
      throw new ShouldNotBeNullException(pMaybeErrorMessage);

   return pObject;
}

使用了这样的东西:

int Func(string? param) =>
   param
   .MaybeThrow(nameof(param) + " was null")
   .Length;

您可以为此使用 [NotNull],因此编译器了解到在调用 Validate.NotNull 之后,该值永远不会是 null.

using System.Diagnostics.CodeAnalysis;

public static class Validate
{
   public static void NotNull([NotNull]object? value, string parameterName, string? field = null)
   {
     if (value == null) throw new ArgumentNullException(parameterName + (field == null ? string.Empty : "." + field));
   }
}

结果:这将不再发出警告:

int Func(string? param)
{
    Validate.NotNull(param, nameof(param));
    return param.Length;
}

旁注 - Func 方法的签名

当然问题是为什么Func方法没有签名:

int Func(string param) // no null allowed

如果不行,您也可以使用另一个属性 [DisallowNull],所以

int Func([DisallowNull] string? param) // gives warning if called with null compile time

旁注 - 更多属性

还有更多超棒的属性

勾选Microsoft docs

这是我的看法:)

int Func(string? param)
{
        return param?.Length ?? throw new ArgumentNullException(nameof(param));
}