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