C# 項目的 nullable 檢查
C# nullable 按照修飾變量類型不同, 分成兩種情況:
1. nullable value type, 照常理來講, value 類型的變量不能設為null, 在C# 2.0為了方便程序員使用基礎類型變量來存儲DB null值, 為value type引入的 nullable 特性, 比如 int? a=null , 這里的 int? 相當于 Nullable<int>.
2. nullable ref type, 照常理來講, ref 類型變量天然可以設置為null, 但當今計算機語言界認為這種隱含的可以賦值為null的變量, 會引起很多預期之外的問題, 所以現在的編程語言都傾向于更嚴格限制null, C# 8為了響應這一潮流也對ref type 可空性做了限制,
簡言之, ref type的nullable特性, 是用來限制 ref type 賦值為 null, 盡量規避 NullReferenceException 異常; 而 value type的 nullable 特性為值類型增加可空的能力, 因為是基于值類型, 所以并不會意外產生 NullReferenceException 異常.
下面是一個table和對象的字段映射定義,
CREATE TABLE [dbo].[People]( [Name] [nvarchar](50) NOT NULL, [BirthDate] [datetime] NULL, [FavoriteMovie] [nvarchar](50) NULL, [FavoriteNumber] [int] NULL ) ON [PRIMARY]
//BirthDate and FavoriteNumber are nullable value types (nullable DateTime and nullable int respectively).
//FavoriteMovie is a string, which is nullable (it’s a reference type). public class Person { public string Name { get; set; } public DateTime? BirthDate { get; set; } public string? FavoriteMovie { get; set; } public int? FavoriteNumber { get; set; } }
在C#7(含7)之前 reference 變量可以為null , 但在C#8為了盡量避免 NullReferenceException 異常,引入了breaking change, 默認情況下reference 不可為null.
//C# 7 private string str=null ; //C# 8 private string str; //不能為null //C# 8, 如果需要為空 private string? str=null ;
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>CS8618</NoWarn>
</PropertyGroup>
Nullable 檢查機制底層是通過 nullable context來實現的, 該上下文提供兩種特性, 第1特性是將string? 這樣的類型編譯到二進制文件中, 即二進制文件中保留 annotations metadata, 第2個特性是, 編譯過程會生成相關的告警.
所以 <Nullabe> 的取值有 enable/disable/warnings/annotations 4種, 4種類型涉及兩個維度, 警告上下文和注解上下文的開啟,
enable: 同時開啟nullable context的兩個特性
disable: 完全關閉 nullable context 的兩個特性, 代碼中也不允許通過 string? 來定義變量.
warnings: 關閉注解上下文, 僅僅開啟警告上下文, 簡單理解: 編譯器不會將nullable相關的類型 metadata 編譯到二進制文件, 但編譯過程對于違反nullable規則, 會報 warning.
annotations: 開啟 annotations 特性, 但關閉編譯器告警.
實際項目的問題:

問題1: 我們能確定賦值不會為null, 但編譯器推斷為空, 怎么調教編譯器呢?
方案: 在代碼中加上下面的方法即可.
ArgumentNullException.ThrowIfNull(keyValuePairs);
問題2: [DisallowNull] 注解和 T 的區別, [AllowNull] 和 T? 和Nullable<T> 的區別:
[DisallowNull] string a1="a" ; string a2="a";
上面代碼在C#8是沒有區別的, [DisallowNull] 常用于泛型類定義.
[AllowNull] string a1="a" ; string? a2="a"; Nullable<string> a3="a";
上面代碼在C#8是沒有區別的, [AllowNull] 常用于泛型類定義.
問題3: 強制干預編譯器賦null值
string a = null; // warning string b = null!; // ok string c = default!; // ok
問題4: 如何為老項目啟用nullable檢查
csproj文件中, 啟用nullable檢查,
然后先為每個cs文件加上下面的指令
#nullable disable
然后一個一個文件開啟, 并修正代碼.
=================================
參考
=================================
C# 8: Nullable Reference Types - Meziantou's blog

浙公網安備 33010602011771號