C#將引入可空的引用型別
是的,標題沒錯。C#其中一份新提案假定,所有的引用型別在預設情況下都是不可空的。在新語法下,你需要顯式地標明一個引用變數是可空的,就像對值型別所做的那樣。
\\和值型別一樣,T是指不可空型別,而T?是指可空型別。以下情況會產生警告:
\\- 取消對可空變數的引用;\\t
- 一個可空變數或引數被賦值給一個不可空變數;\\t
- 從T?[]轉換到T[];\\t
- 從T[]轉換到T?[];\\t
- 將一個空字面量賦值給一個不可空變數或引數;\\t
- 建構函式沒有給所有的不可空欄位賦值;\
對於前兩種情況,如果你使用了感嘆號運算子(x!)或者編譯器能夠證明已經執行了null檢查,那麼警告將被忽略。
\\實現細節
\\底層編譯器將會忽略可空註解,因此,那不是問題。不過,在程式集級,應該有某種標記,可以說明庫在編譯時啟用了可空註解。
\\由於所有這類可空的東西從技術上講都是一種破壞性修改,所以當前的計劃是允許開發人員選擇下面的類別:
\\- 可空警告;\\t
- 不可空警告;\\t
- 警告來自其他檔案中的註解。\
提案繼續寫道:
\\\\\選擇參與的粒度表明,這是一個類似分析器的模型,大段的程式碼通過編譯指令選擇參與和退出,使用者可以選擇安全級別。此外,每個庫的選項(“在準備好應對後果之前,忽略JSON.NET中的註解”)可以表示為程式碼中的屬性。
\
根據預期,這種設計要達到以下三個目的:
\\- 使用者可以像他們希望的那樣逐步採用可空屬性檢查;\\t
- 庫作者可以新增可空屬性註解,而不必擔心破壞使用者的程式碼;\\t
- 除此之外,沒有“配置噩夢”之感。\
對於同一個方法,你不必進行可空和不可空的過載。雖然從技術上講,CLR支援這樣做,但那不是CLS或者通用語言規範的組成部分。這意味著,大多數編譯器都會不知道發生了什麼。HaloFour作了如下說明:
\\\\\\
modreq
不是CLS。modopt
確實支援過載,但需要具體瞭解所有重要編譯器的這個部分,因為至少要將修飾符複製到呼叫簽名裡。兩者都會破壞與現有方法簽名的相容。對於希望在整個BCL快速傳播的東西來說,使用modopt
會成為巨大的障礙。
泛型
\\在使用泛型時,以下情況會出現額外的警告:
\\- 從C\u0026lt;T\u0026gt;轉換到C\u0026lt;T?\u0026gt;,除非型別引數是協變數(出);\\t
- 從C\u0026lt;T?\u0026gt;轉換到C\u0026lt;T\u0026gt;,除非型別引數是反變數(入);\\t
- 使用C\u0026lt;T?\u0026gt;,然後將型別引數限制為不可為空。\
使用“class”,則泛型強制非空。使用“class?”則允許空值。該提案繼續寫道:
\\\\\如果一個型別引數沒有約束,或者只有可空約束,則情況會稍微複雜一些:這意味著,相應的型別引數既可以為空,也可以不為空。在那種情況下,安全的做法是將型別引數既作為可空引數來處理,又作為不可空引數來處理,任何一個不滿足,就發出警告。
\
陣列
\\陣列是一項特殊的挑戰,因為在一個不可為空的陣列中,不一定可以確保每個槽都有一個值。
\\\\\對於一個非空引用陣列,我們無法通過充分地跟蹤來保證陣列的所有元素都被初始化。不過,在從陣列讀取資料或者傳遞陣列之前,如果新建立的陣列沒有元素被賦值,我們就會發出警告。那應該可以處理常見的情況,而又不帶來太多干擾。
\
開放性設計問題
\\使用default(T)應該發出警告嗎?還是說假定它會返回T?,而不是T?
\\可以刪除區域性變數上的?而根據使用情況推斷其可空性嗎?
\\引數可以使用T! x模式自動生成null檢查嗎?
\\可以調整一下可空值型別,以便讓開發人員可以使用x.method代替x.Value.method嗎(這用在當x已知非空時,比如已經成功完成了null檢查)?
\\更多資訊
\\相關文章
- 如何將C# 7類庫升級到C# 8?使用可空引用型別C#型別
- C#8.0 可空引用型別C#型別
- 瞭解下C# 可空型別(Nullable)C#型別Null
- 為你的專案啟用可空引用型別型別
- c#:值型別&引用型別C#型別
- 快速瞭解C# 8.0中“可空引用型別(Nullable reference type)”語言特性C#型別Null
- c#中值型別和引用型別的區別C#型別
- Kotlin可空型別與非空型別以及`lateinit` 的作用Kotlin型別
- 原來C#的可空型別可以直接參與計算C#型別
- C#引用型別和值型別在堆、棧中的儲存C#型別
- C#學習筆記之值型別與引用型別C#筆記型別
- C#程式設計引用型別和值型別 以及引用傳遞和值傳遞C#程式設計型別
- Go 的引用型別Go型別
- 值型別與引用型別的區別型別
- Java的基本型別和引用型別Java型別
- 值型別和引用型別型別
- JavaScript引用型別-Object型別JavaScript型別Object
- js引用型別JS型別
- javascript:引用型別JavaScript型別
- JavaScript值型別和引用型別JavaScript型別
- ECMAScript 原始型別與引用型別型別
- js基本型別和引用型別區別JS型別
- Hellow C# unity學習記錄(7)值型別引用型別以及引數傳遞C#Unity型別
- JavaScript - 基本型別與引用型別值JavaScript型別
- 引用型別的深拷貝型別
- Java引用型別解析:掌握強引用、軟引用、弱引用和幻象引用的妙用Java型別
- Golang 引用型別-mapGolang型別
- 引用型別之Object型別Object
- 基本資料型別與API引用型別的使用資料型別API
- JavaScript中的Object的引用型別JavaScriptObject型別
- 從賦值看基本型別和引用型別的區別賦值型別
- C#支援將json中的多種型別反序列化為object型別C#JSON型別Object
- JS篇-基本型別和引用型別、typeofJS型別
- C#學習 [型別系統] 名稱空間(12)C#型別
- java的四大引用型別Java型別
- Java引用型別與WeakHashMapJava型別HashMap
- Java引用型別原理剖析Java型別
- Python3學習 (變數+值型別+引用型別+列表的可變+元組的不可變+運算子號)Python變數型別
- Java中的基本資料型別與引用資料型別Java資料型別