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#也对ref type 可空性做了限制,
简言之, ref type的nullable特性, 是用来明确 nullable 定义,尽量规避 NullReferenceException 异常; 而 value typ的 nullable 特性是扩大null的使用范围.
下面是一个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 ;
.Net6 生成的项目, 默认会启用 nullable 检查, 这样会大大避免 NullReferenceException 异常, 但这仅仅是个编译警告,
csproj 文件设置. 如果要上升到报错级别, 需要设置 <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup>
Nullable 的取值有 enable/disable/warnings/annotations 4种, 4种类型涉及两个维度, 警告上下文和注解上下文的开启,
enable: 意义很明确, 启用最严格的方式, .net 6 默认方式. 即编译器对表达式推断和声明不符合, 将会报编译错误.
disable: 老项目默认方式, 即编译器不对nullable做任何推断, 也不会有任何警告.
warnings: 即关闭注解上下文, 仅仅开启警告上下文, 简单理解: 编译器不对引用类型变量做推断, 仅对值类型做简单推断, 违反nullable规则, 仅仅报 warning.
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律