快速瞭解C# 8.0中「可空引用類型(Nullable reference type)」語言特性

Visual C# 8.0中引入了可空引用類型(Nullable reference type),經過編譯器提供的強大功能,幫助開發人員儘量地規避由空引用帶來的代碼問題。這裏我大體介紹一下可空引用類型的基本內容。
剛開始接觸這個語言特性的時候,可能會不太容易理解。引用類型原本不就是能夠爲空(null)的麼,爲啥還要特別地引入「可空引用類型」的概念呢?其實這是從編譯器的角度要求開發人員在編程的時候就考慮某個變量是否有可能爲空,從而儘量地減小由空引用所帶來的代碼錯誤。
假設有以下類:編程

class Student
{
    public Student(string name, DateTime dayOfBirth)
        => (Name, DayOfBirth) = (name, dayOfBirth);

    public string Name { get; set; }

    public DateTime DayOfBirth { get; set; }

    public string Notes { get; set; }
}

此類定義了一個「學生」實體的基本信息,爲了簡化起見,這裏只列出了須要討論的幾個屬性:框架

  • Name:學生姓名
  • DayOfBirth:學生生日
  • Notes:對學生信息的一些備註

假設咱們有兩個操做:在全部學生中,找出全部具備備註信息的學生,以及對全部學生按姓名排序,在C#中很容易使用Linq來實現:函數

var studentsHasNotes = students.Where(s => s.Notes.Length > 0);

以及:code

var orderedStudents = students.OrderBy(s => s.Name);

到目前爲止沒啥問題,程序可以正常運行。然而仔細進行代碼審查不難發現,在獲取全部具備備註信息的學生的代碼中(也就是上面第一段代碼中),有可能出現空引用的異常,由於對於一個「學生」實體來講,它的Notes屬性是有可能爲null的。
如今咱們打開「可空引用類型」這一語言特性,打開方式主要有兩種:能夠在項目級別,編輯csproj項目文件進行設置,也能夠經過#nullable預編譯指令來實現:對象

  • 編輯csproj項目文件,加入<Nullable>enable</Nullable>便可:
    image
  • 經過#nullable預編譯指令來實現,只須要在代碼中須要的地方加入#nullable指令便可:
    image

啓用「可空引用類型」這一語言特性以後你會發現,在上面的Student類的構造函數處出現了一個警告,提示在構造函數執行完成時,不可爲空的「Notes」屬性須要有一個不爲空的值,建議將其設置爲可空的string類型。爲何編譯器僅提示Notes有可能爲空,而不是Name屬性呢?由於構造函數中已經爲Name賦值了,所以,對於任何一個Student的對象,Name不可能爲空,而Notes則否則。blog

image

Name不可能爲空?它不是string類型麼?萬一在代碼中它爲空了怎麼辦?別急,編譯器是不會容許出現這種狀況的:排序

image

在此,咱們將Notes屬性設置爲string?類型,因而你會發現,位於構造函數上的警告信息已經沒有了,由於咱們容許Student對象能夠沒有Notes數據,但在「找出全部具備備註信息的學生」這一操做時,又會出現警告,提示說Notes有可能爲空:繼承

image

因而,你會發現,在啓用了可空引用類型的語言特性後,咱們就須要仔細考察Student類型中的每個引用類型的屬性,看它在實際應用中是否有可能爲空,若是可能爲空,則用可空引用類型來定義屬性,以後編譯器就會幫助你來分析哪些地方有可能存在空引用。開發

在上面的「找出全部具備備註信息的學生」例子中,若是你以爲Notes確定不會爲空,那麼也可使用「!」操做符來覆蓋編譯器的警告信息,好比:get

image

如今流行的.NET開源框架基本上都已經支持了可空引用類型了,並且若是你是一名開源框架的開發人員,也強烈建議在你的框架中啓用這一語言特性來儘量地避免空引用問題。好比,若是你在代碼中啓用了可空引用類型特性,那麼當你從Newtonsoft.Json的JsonConverter類繼承時,你會發現,你必須使用可空引用類型的函數重載:

image

但若是你沒有啓用可空引用類型特性,那麼當你從Newtonsoft.Json的JsonConverter類繼承時,你會發現,重載函數的簽名與之前同樣:

image

好了,對於C# 8.0的「可空引用類型」大體就介紹這麼多,相信應該已經基本上歸納了它的要點和使用方式,在平常開發中應該夠用了。

相關文章
相關標籤/搜索