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)