可空引用型別是c#8.0計畫新增的乙個功能,不過已經發布了預覽版本,今天我們來體驗一下可空引用型別。
安裝roslyn擴充套件預覽版本:
關閉所有執行的visual studio;
執行zip根目錄中的 .\install.bat 指令碼(如果需要解除安裝擴充套件,可以執行.\uninstall.bat指令碼);
在語法上,可為空引用型別與可為空值型別使用的語法是一致的,在型別後面追加?即可。
class person
我們都知道當初微軟在增加可為空值型別的時候,實際是在框架中增加了system.nullable<>
型別,您肯定會問,可為空引用型別以框架中又增加了什麼新的型別。
我們來看乙個演示:
class program
}
輸出結果:
您是否覺得奇怪,怎麼輸出的是system.string
,是的,其實微軟在框架中沒有加入任何型別,我們person
型別進行編譯後,再通過dotpeek進行反編譯,就明白到底發生了什麼。
反編譯後的結果:
internal class person
只是在middlename
欄位上增加了system.runtime.compilerservices.nullableattribute
標記。
我們來看一看屬性、引數、變數、返回值編譯之前與編譯之後的比對結果。
屬性
// 編譯前:
public string? middlename
// 編譯後:
[nullable]
public string middlename
引數
// 編譯前:
public person(string? middlename )
// 編譯後:
public person([nullable] string middlename)
返回值
// 編譯前:
public string? dosomething()
// 編譯後:
[return: nullable]
public string dosomething()
變數
// 編譯前:
string? name;
// 編譯後:
string name;
這裡除了變數,其它的都使用了nullableattribute
標記進行的修飾。
通過上面的章節,我們知道,可為空引用型別只是在引數、屬性、引數和返回值中使用nullableattribute
標記進行修飾,實際上對程式的正常執行沒有任何的影響。那麼它可以為我們做什麼呢?
在c#中不能表達這個變數、引數、字段、屬性,返回值等可能為null
或不能為null
,可為空型別可以幫我們解決這個問題。
class person
這個型別的可以表示每乙個人都應該 fristname 和 lastname ,但是不是每乙個人都應該有 middlename。
可為空引用型別的另乙個好處是編譯器可以幫助我們檢測**,比如對於直接使用可為空引用型別的屬性,編譯器會發出警告。
void m(person p)
writeline(p.middlename!.length); // ok
}class person
編譯器會幫我們做以下幾點檢測:
如果給非可為空引用型別賦null
值或可為空引用型別的值,則會發出警告;
如果直接使用可為空引用型別,則會發出警告;
如果從來沒有給非可為空引用型別的屬性賦值,則會發出警告;
如果需要直接使用可為空引用型別,需要使用!符號告訴編譯器,您已經確認過該值不可能為空。
當然這只是編譯器的行為,可以禁用與之相關的警告提示。空引用型別是乙個語法糖,只是在編譯器的層面幫我們發現可能發生的問題,對程式的正常執行沒有任何作用。
C 將引入可空的引用型別
是的,標題沒錯。c 其中乙份新提案假定,所有的引用型別在預設情況下都是不可空的。在新語法下,你需要顯式地標明乙個引用變數是可空的,就像對值型別所做的那樣。u0026 xd n u0026 xd n 和值型別一樣,t是指不可空型別,而t?是指可空型別。以下情況會產生警告 u0026 xd n u002...
C 將引入可空的引用型別
是的,標題沒錯。c 其中乙份新提案假定,所有的引用型別在預設情況下都是不可空的。在新語法下,你需要顯式地標明乙個引用變數是可空的,就像對值型別所做的那樣。和值型別一樣,t是指不可空型別,而t?是指可空型別。以下情況會產生警告 對於前兩種情況,如果你使用了感嘆號運算子 x 或者編譯器能夠證明已經執行了...
C 將引入可空的引用型別
是的,標題沒錯。c 其中乙份新提案假定,所有的引用型別在預設情況下都是不可空的。在新語法下,你需要顯式地標明乙個引用變數是可空的,就像對值型別所做的那樣。和值型別一樣,t是指不可空型別,而t?是指可空型別。以下情況會產生警告 對於前兩種情況,如果你使用了感嘆號運算子 x 或者編譯器能夠證明已經執行了...