C 8 0可空引用型別的使用注意記錄

2022-09-26 03:03:07 字數 2140 閱讀 1651

前言

最近vs2019正式版發布了,裝下來順便試用了一下c#8.0,最大的看點應該就是可空引用型別了。不過c#8.0仍然處於beta的狀態,而且試用時也遇到了幾個坑。

背景知識說明:

所謂的可空引用型別是指,一旦啟用了可空引用型別這個新特徵,引用型別將預設被視為不可空,無法賦予null,除非手工將它設為可空引用型別。

實戰示例:

首先是新建乙個c#的專案,在 專案檔案(.csproj)裡加入兩行配置,目的是啟用「c#8.0語言」和「可空引用型別」:

8.0enable

整個檔案看起來是這樣的:

這樣就算是整個專案全域性啟用了可空引用型別了。

注意:在vs2019正式版中,使用

enable

而不是使用

true

後者在正式版中已經失效了。

如果不希望全域性啟用可空引用型別的話,可以在程式**中加入以下編譯指令:

#nullable enable

這樣可以在加入了該指令的檔案中,單獨啟用可空引用型別。但是,極度不推薦這種做法。為什麼呢?因為該指令僅僅在該檔案中有效,不能跨檔案生效,從而無法阻止null逃逸到使用了該指令的檔案中,也就是說,用了也等於沒用。

乙個很簡單的例子足www.cppcns.com以證明:

注意上面專案檔案中並沒有全域性啟用可空引用型別,而下面的class1.cs中使用了編譯器指令來單獨啟用可空引用型別。

從執行結果可見,空引用仍然逃逸到使用了該指令的作用域中了。別說編譯錯誤,連程式設計客棧編譯警告都沒有。完全達不到理想的效果。

因此,強烈建議在專案檔案中全域性啟用可空引用型別,而不是在某個原始檔中單獨使用。

另外,還有一點要注意的是,即使啟用了可空引用型別後,預設情況下,即使對不可空引用賦予null,編譯器也只會生成編譯警告,而不是編譯錯誤。仍然是能夠編譯通過的。乙個大專案中,編譯警告不可避免,甚至可能會很多,從而淹沒了「給不可空引用型別賦予空值」這種不起眼的警告。程式設計客棧

因此,建議將特定的警告視為錯誤。警告編號為8600、8625、8618、8604,或者將所有警告視為錯誤。具體是在專案檔案中加入以下設定(見圖一):

8600 8625 8618 8604

或者在專案編輯器中設定也可以:

這是我自己測試得出的結果,可能還有其它潛在的相關警告編號我沒有測試出來。如果有誰知道的話,告訴我一下,謝謝。

做好這些配置之後,可以看到引用型別預設都不能賦予空值了:

這時候普通的引用型別的變數和引數都不能設為null了。

這樣可以防止空值擴散開來,引起惱人的空引用異常。

但是,這裡有個坑需要注意!!!!

struct裡不適用可空引用的規則!!

struct裡不適用可空引用的規則!!

struct裡不適用可空引用的規則!!

這種情況下直接執行,仍然會丟擲空引用異常!!!c#8.0仍未能完全封堵住空引用的逃逸。

其實我還是比較贊同用不可空引用型別的方案的,而不是可空引用型別的方案。畢竟我想要的,只不過是乙個不可空的斷言,只是想利用不可空引用來劃分安全邊界,從而防止空值的擴散。簡單來說就是想將變數和引數明確宣告為不可空引用型別。因為歷史和現實的原因,大量的庫都還沒能全面使用可空引用型別。這種情況下,只有我使用可空引用型別,是不靠譜的。無法劃分安全邊界。

然而c#選擇了可空引用型別的方案,而且還不是強制啟用,而且預設只是警告。。跟沒有一樣。。。

比方說,我使用了乙個第三方庫專案,而空值的**是正好是該庫專案的,而我對這個庫並沒有源**或者修改許可權。這時候就無法阻止空值逃逸到我的專案中了。

還是之程式設計客棧前的**,只是稍微做一下修改。新增了乙個庫專案classlibrary1,這個庫並沒有使用可空引用型別。

庫的**如下:

很簡單,就是libclass3.getinstance()本應該返回libclass2的例項,但是出於某種原因,返回了null。但是我的專案中使用了libclass2和libclass3。我的專案是全域性啟用了可空引用型別的:

編譯正常,毫無警告和錯誤。一旦執行,則丟擲空引用異常:

可見,目前來說,c#8.0的可空引用型別並不能解決外源性的空值擴散,只能解決內源性的空值擴散,無法跨模組生效。還是洗洗睡吧。

參考資料:

程式設計客棧eatures/nullable-reference-types.md

總結本文標題: c# 8.0可空引用型別的使用注意記錄

本文位址:

C 8 0可空引用型別的使用注意要點

c 8.0可空引用型別的使用注意要點 最近vs2019正式版發布了,裝下來順便試用了一下c 8.0,最大的看點應該就是可空引用型別了。不過c 8.0仍然處於beta的狀態,而且試用時也遇到了幾個坑。背景知識說明 所謂的可空引用型別是指,一旦啟用了可空引用型別這個新特徵,引用型別將預設被視為不可空,無...

C 8 0 可為空的引用型別

在寫反射建立例項時,報錯 將 null 文字或可能的 null 值轉換為不可為 null 型別 因為之前也寫過一模一樣的 報錯了很懵,就查了一下原因,順帶學習下 可以查到微軟官網給出的解釋 c 8.0 開始,可以使用可為 null 的引用型別 可為null的引用型別 c 引用 可為空的值型別 c 參...

C 可空引用型別

可空引用型別是c 8.0計畫新增的乙個功能,不過已經發布了預覽版本,今天我們來體驗一下可空引用型別。安裝roslyn擴充套件預覽版本 關閉所有執行的visual studio 執行zip根目錄中的 install.bat 指令碼 如果需要解除安裝擴充套件,可以執行.uninstall.bat指令碼 ...