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);
以及:
var orderedStudents = students.OrderBy(s => s.Name);
到目前為止沒啥問題,程式能夠正常運行,然而仔細進行代碼審查不難發現,在獲取所有具有備注資訊的學生的代碼中(也就是上面第一段代碼中),有可能出現空參考的例外,因為對于一個“學生”物體來說,它的Notes屬性是有可能為null的,
現在我們打開“可空參考型別”這一語言特性,打開方式主要有兩種:可以在專案級別,編輯csproj專案檔案進行設定,也可以通過#nullable預編譯指令來實作:
- 編輯csproj專案檔案,加入
<Nullable>enable</Nullable>即可:

- 通過#nullable預編譯指令來實作,只需要在代碼中需要的地方加入#nullable指令即可:

啟用“可空參考型別”這一語言特性之后你會發現,在上面的Student類的建構式處出現了一個警告,提示在建構式執行完成時,不可為空的“Notes”屬性需要有一個不為空的值,建議將其設定為可空的string型別,為什么編譯器僅提示Notes有可能為空,而不是Name屬性呢?因為建構式中已經為Name賦值了,因此,對于任何一個Student的物件,Name不可能為空,而Notes則不然,

Name不可能為空?它不是string型別么?萬一在代碼中它為空了怎么辦?別急,編譯器是不會允許出現這種情況的:

在此,我們將Notes屬性設定為string?型別,于是你會發現,位于建構式上的警告資訊已經沒有了,因為我們允許Student物件可以沒有Notes資料,但在“找出所有具有備注資訊的學生”這一操作時,又會出現警告,提示說Notes有可能為空:

于是,你會發現,在啟用了可空參考型別的語言特性后,我們就需要仔細考察Student型別中的每一個參考型別的屬性,看它在實際應用中是否有可能為空,如果可能為空,則用可空參考型別來定義屬性,之后編譯器就會幫助你來分析哪些地方有可能存在空參考,
在上面的“找出所有具有備注資訊的學生”例子中,如果你覺得Notes肯定不會為空,那么也可以使用“!”運算子來覆寫編譯器的警告資訊,比如:

現在流行的.NET開源框架基本上都已經支持了可空參考型別了,而且如果你是一名開源框架的開發人員,也強烈建議在你的框架中啟用這一語言特性來盡可能地避免空參考問題,比如,如果你在代碼中啟用了可空參考型別特性,那么當你從Newtonsoft.Json的JsonConverter類繼承時,你會發現,你必須使用可空參考型別的函式多載:

但如果你沒有啟用可空參考型別特性,那么當你從Newtonsoft.Json的JsonConverter類繼承時,你會發現,多載函式的簽名與以前一樣:

好了,對于C# 8.0的“可空參考型別”大致就介紹這么多,相信應該已經基本上概括了它的要點和使用方式,在日常開發中應該夠用了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/270416.html
標籤:C#
上一篇:C# 內部類與外部類的訪問
