C#新特性之可空引用類型
安裝
您必須下載Visual Studio 2017 15.5預(yù)覽版(目前最新發(fā)布版本是15.4),下載地址:https://www.visualstudio.com/en-us/news/releasenotes/vs2017-preview-relnotes。
安裝Roslyn擴(kuò)展預(yù)覽版本:
- 下載并解壓 Roslyn_Nullable_References_Preview.zip [最新版本 11/15/17];
- 關(guān)閉所有運(yùn)行的Visual Studio;
- 運(yùn)行zip根目錄中的 .\install.bat 腳本(如果需要卸載擴(kuò)展,可以運(yùn)行.\uninstall.bat腳本);
語(yǔ)法與類型
在語(yǔ)法上,可為空引用類型與可為空值類型使用的語(yǔ)法是一致的,在類型后面追加 ? 即可。
class Person
{
public string FirstName;
public string? MiddleName;
public string LastName;
}我們都知道當(dāng)初微軟在增加可為空值類型的時(shí)候,實(shí)際是在框架中增加了System.Nullable<>類型,您肯定會(huì)問(wèn),可為空引用類型以框架中又增加了什么新的類型。
我們來(lái)看一個(gè)演示:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(typeof(string?).FullName);
}
}輸出結(jié)果:

您是否覺(jué)得奇怪,怎么輸出的是System.String,是的,其實(shí)微軟在框架中沒(méi)有加入任何類型,我們Person類型進(jìn)行編譯后,再通過(guò)dotPeek進(jìn)行反編譯,就明白到底發(fā)生了什么。
反編譯后的結(jié)果:
internal class Person
{
public string FirstName;
[Nullable]
public string MiddleName;
public string LastName;
}只是在MiddleName字段上增加了System.Runtime.CompilerServices.NullableAttribute標(biāo)記。
我們來(lái)看一看屬性、參數(shù)、變量、返回值編譯之前與編譯之后的比對(duì)結(jié)果。
屬性
// 編譯前:
public string? MiddleName { get; set; }
// 編譯后:
[Nullable]
public string MiddleName { [return: Nullable] get; [param: Nullable] set; }參數(shù)
// 編譯前:
public Person(string? middleName )
{
this.MiddleName = middleName;
}
// 編譯后:
public Person([Nullable] string middleName)
{
this.MiddleName = middleName;
}返回值
// 編譯前:
public string? DoSomething()
{
return null;
}
// 編譯后:
[return: Nullable]
public string DoSomething()
{
return (string) null;
}變量
// 編譯前:
string? name;
// 編譯后:
string name;這里除了變量,其它的都使用了NullableAttribute標(biāo)記進(jìn)行的修飾。
它可以做什么?
通過(guò)上面的章節(jié),我們知道,可為空引用類型只是在參數(shù)、屬性、參數(shù)和返回值中使用NullableAttribute標(biāo)記進(jìn)行修飾,實(shí)際上對(duì)程序的正常運(yùn)行沒(méi)有任何的影響。那么它可以為我們做什么呢?
表達(dá)意圖
在C#中不能表達(dá)這個(gè)變量、參數(shù)、字段、屬性,返回值等可能為null或不能為null,可為空類型可以幫我們解決這個(gè)問(wèn)題。
class Person
{
public string FirstName; // 不為null
public string? MiddleName; // 可能為null
public string LastName; // 不為null
}這個(gè)類型的可以表示每一個(gè)人都應(yīng)該 FristName 和 LastName ,但是不是每一個(gè)人都應(yīng)該有 MiddleName。
編譯器檢測(cè)
可為空引用類型的另一個(gè)好處是編譯器可以幫助我們檢測(cè)代碼,比如對(duì)于直接使用可為空引用類型的屬性,編譯器會(huì)發(fā)出警告。
void M(Person p)
{
p.FirstName = null; // 1 WARNING: Cannot convert null to non-nullable reference。
p.LastName = p.MiddleName; // 2 WARNING: Possible null reference assignment.
string s = default(string); // 3 WARNING: Cannot convert null to non-nullable reference。
if (p.MiddleName != null)
{
WriteLine(p.MiddleName.Length); // ok
}
WriteLine(p.MiddleName!.Length); // ok
}
class Person
{
public string FirstName; // 4 WARNING: Non-nullable field 'FirstName' is uninitialized.
public string? MiddleName;
public string LastName; // 5 WARNING: Non-nullable field 'LastName' is uninitialized.
}編譯器會(huì)幫我們做以下幾點(diǎn)檢測(cè):
- 如果給非可為空引用類型賦
null值或可為空引用類型的值,則會(huì)發(fā)出警告; - 如果直接使用可為空引用類型,則會(huì)發(fā)出警告;
- 如果從來(lái)沒(méi)有給非可為空引用類型的屬性賦值,則會(huì)發(fā)出警告;
- 如果需要直接使用可為空引用類型,需要使用 ! 符號(hào)告訴編譯器,您已經(jīng)確認(rèn)過(guò)該值不可能為空。
當(dāng)然這只是編譯器的行為,可以禁用與之相關(guān)的警告提示。
總結(jié)
空引用類型是一個(gè)語(yǔ)法糖,只是在編譯器的層面幫我們發(fā)現(xiàn)可能發(fā)生的問(wèn)題,對(duì)程序的正常運(yùn)行沒(méi)有任何作用。
到此這篇關(guān)于C#新特性之可空引用類型的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# WinForm實(shí)現(xiàn)自動(dòng)更新程序的方法詳解
這一篇就著重寫(xiě)一下客戶端的代碼,客戶端主要實(shí)現(xiàn)的有:?jiǎn)?dòng)后檢測(cè)本地的xml文件,然后發(fā)送到服務(wù)器獲取需要更新的文件以及版本列表,感興趣的小伙伴可以了解一下2022-10-10
C#實(shí)現(xiàn)的字符串轉(zhuǎn)MD5碼函數(shù)實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)的字符串轉(zhuǎn)MD5碼函數(shù),結(jié)合簡(jiǎn)單實(shí)例形式分析了C#字符串的轉(zhuǎn)換、遍歷、加密等操作技巧,需要的朋友可以參考下2016-07-07
C#在Windows上調(diào)用7-zip實(shí)現(xiàn)壓縮文件
這篇文章主要為大家詳細(xì)介紹了C#如何在Windows上調(diào)用7-zip實(shí)現(xiàn)壓縮文件,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以學(xué)習(xí)一下2023-10-10
詳解c#中Array,ArrayList與List<T>的區(qū)別、共性與相互轉(zhuǎn)換
本文詳細(xì)講解了c#中Array,ArrayList與List<T>的區(qū)別、共性與相互轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12

