C#中被调函数已判空后仍报空引用警告问题的处理方法

语言: CN / TW / HK

本文标题有点难懂,不过我也实在是想不出什么更好的标题了,就请大家研读文章内容吧。最近在审核代码中发现一个有趣的现象,就是在C#中,如果我启用了Nullable Reference Type的功能,并且定义了下面这个扩展方法:

static class Extensions
{
    public static bool IsNullOrEmpty(this SecureString? secureString)
            => secureString == null || secureString.Length == 0;
}

在这个扩展方法中,通过对secureString是否为null或者其长度是否为0进行判定,来返回一个bool值,表示给定的secureString是否为空,或者是否没有包含任何内容。代码的内容非常容易理解,但是,在下面的调用代码中,编译器始终给出警告,表示str变量有可能为空:

static SecureString? GetSecureString(bool shouldReturn)
    => shouldReturn ? new SecureString() : null;

var str = GetSecureString(true);
if (!str.IsNullOrEmpty())
{
    var str2 = str.Length;
    Console.WriteLine(str2);
}

此时你就会觉得疑惑,既然我已经通过自己写的IsNullOrEmpty方法,对SecureString进行空引用判定了,为何编译器仍然给出可能为空的警告呢。其实道理也很简单,IsNullOrEmpty这个方法是我自己取的名字,编译器根本不可能知道这个方法中的业务逻辑到底是在干什么,所以,我们需要告诉编译器,这个函数进行了判空处理。

解决方法就是在函数参数上,加上NotNullWhenAttribute:

static class Extensions
{
    public static bool IsNullOrEmpty([NotNullWhen(false)] this SecureString? secureString)
            => secureString == null || secureString.Length == 0;
}

这就表示当函数返回值为false时,被修饰的参数对象一定不会为空,于是,编译器就能得知这个信息,并作出正确的警告处理。在使用了这个C#特性之后,警告就消失了:

(总访问量:23;当日访问量:23)