C#将引入可空的引用类型
是的,標題沒錯。C#其中一份新提案假定,所有的引用類型在默認情況下都是不可空的。在新語法下,你需要顯式地標明一個引用變量是可空的,就像對值類型所做的那樣。
和值類型一樣,T是指不可空類型,而T?是指可空類型。以下情況會產生警告:
取消對可空變量的引用;
一個可空變量或參數被賦值給一個不可空變量;
從T?[]轉換到T[];
從T[]轉換到T?[];
將一個空字面量賦值給一個不可空變量或參數;
構造函數沒有給所有的不可空字段賦值;
對于前兩種情況,如果你使用了感嘆號運算符(x!)或者編譯器能夠證明已經執行了null檢查,那么警告將被忽略。
實現細節
底層編譯器將會忽略可空注解,因此,那不是問題。不過,在程序集級,應該有某種標記,可以說明庫在編譯時啟用了可空注解。
由于所有這類可空的東西從技術上講都是一種破壞性修改,所以當前的計劃是允許開發人員選擇下面的類別:
可空警告;
不可空警告;
警告來自其他文件中的注解。
提案繼續寫道:
選擇參與的粒度表明,這是一個類似分析器的模型,大段的代碼通過編譯指令選擇參與和退出,用戶可以選擇安全級別。此外,每個庫的選項(“在準備好應對后果之前,忽略JSON.NET中的注解”)可以表示為代碼中的屬性。
根據預期,這種設計要達到以下三個目的:
用戶可以像他們希望的那樣逐步采用可空屬性檢查;
庫作者可以添加可空屬性注解,而不必擔心破壞用戶的代碼;
除此之外,沒有“配置噩夢”之感。
對于同一個方法,你不必進行可空和不可空的重載。雖然從技術上講,CLR支持這樣做,但那不是CLS或者通用語言規范的組成部分。這意味著,大多數編譯器都會不知道發生了什么。HaloFour作了如下說明:
modreq不是CLS。modopt確實支持重載,但需要具體了解所有重要編譯器的這個部分,因為至少要將修飾符復制到調用簽名里。兩者都會破壞與現有方法簽名的兼容。對于希望在整個BCL快速傳播的東西來說,使用modopt會成為巨大的障礙。
泛型
在使用泛型時,以下情況會出現額外的警告:
從C<T>轉換到C<T?>,除非類型參數是協變量(出);
從C<T?>轉換到C<T>,除非類型參數是反變量(入);
使用C<T?>,然后將類型參數限制為不可為空。
使用“class”,則泛型強制非空。使用“class?”則允許空值。該提案繼續寫道:
如果一個類型參數沒有約束,或者只有可空約束,則情況會稍微復雜一些:這意味著,相應的類型參數既可以為空,也可以不為空。在那種情況下,安全的做法是將類型參數既作為可空參數來處理,又作為不可空參數來處理,任何一個不滿足,就發出警告。
數組
數組是一項特殊的挑戰,因為在一個不可為空的數組中,不一定可以確保每個槽都有一個值。
對于一個非空引用數組,我們無法通過充分地跟蹤來保證數組的所有元素都被初始化。不過,在從數組讀取數據或者傳遞數組之前,如果新創建的數組沒有元素被賦值,我們就會發出警告。那應該可以處理常見的情況,而又不帶來太多干擾。
開放性設計問題
使用default(T)應該發出警告嗎?還是說假定它會返回T?,而不是T?
可以刪除局部變量上的?而根據使用情況推斷其可空性嗎?
參數可以使用T! x模式自動生成null檢查嗎?
可以調整一下可空值類型,以便讓開發人員可以使用x.method代替x.Value.method嗎(這用在當x已知非空時,比如已經成功完成了null檢查)?
原文地址:http://www.infoq.com/cn/news/2017/04/CSharp-Nullable
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的C#将引入可空的引用类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: netcore实践:跨平台动态加载nat
- 下一篇: 理解C# 4 dynamic(1) -