C# 可空引用類型解析
????可空引用類型是C#8.0計(jì)劃新增的一個(gè)功能,今天我們來(lái)體驗(yàn)一下可空引用類型。
語(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;[]public string MiddleName;public string LastName;}
只是在MiddleName字段上增加了System.Runtime.CompilerServices.NullableAttribute標(biāo)記。
我們來(lái)看一看屬性、參數(shù)、變量、返回值編譯之前與編譯之后的比對(duì)結(jié)果。
屬性
// 編譯前:public string? MiddleName { get; set; }// 編譯后:[]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;}// 編譯后:[]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; // 不為nullpublic string? MiddleName; // 可能為nullpublic 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)有任何作用。
參考資料:
https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/
https://github.com/dotnet/csharplang/wiki/Nullable-Reference-Types-Preview
出處:https://www.cnblogs.com/tdfblog/p/Nullable-Reference-Types-Preview.html
版權(quán)申明:本文來(lái)源于網(wǎng)友收集或網(wǎng)友投稿,僅供學(xué)習(xí)交流之用,如果有侵權(quán),請(qǐng)轉(zhuǎn)告版主或者留言,本公眾號(hào)立即刪除。
支持小微:
騰訊云 新年活動(dòng)!玩服務(wù)器的可以搞搞,老客戶也可以參加!
輕量服務(wù)器??2核4G8M80G?222元/3年??
爆款1核2G云服務(wù)器首年38元??
鏈接:https://curl.qcloud.com/bR8ycXZa
右下角,您點(diǎn)一下在看圖片
小微工資漲1毛
商務(wù)合作QQ:185601686
