C# 可空类型使用方法 C#如何使用Nullable类型

3次阅读

NULLable是c#中包装值类型泛型结构体int?是Nullable的语法糖;它通过hasvalue和value属性支持null语义,需检查hasvalue再访问value,与可空引用类型无关。

C# 可空类型使用方法 C#如何使用Nullable类型

什么是 Nullable<t></t>,和 int? 有什么关系

Nullable<t></t> 是 C# 中用于包装值类型的泛型结构体,让原本不能为 null 的值类型(如 intboolDateTime)可以表示“无值”状态。语法糖 int? 就是 Nullable<int></int> 的简写,二者完全等价。

  • int? 编译后就是 Nullable<int></int>,不是引用类型,不分配在
  • 只有 Struct 类型能作为 T 传给 Nullable<t></t>class 类型本身就能为 null,无需包装
  • Nullable<t></t> 有两个关键属性:HasValuebool)和 ValueT),访问 Value 前必须确认 HasValuetrue,否则抛出 InvalidOperationException

如何安全地获取可空类型的值(避免 InvalidOperationException

直接访问 .Value 是最常见崩溃点。推荐用以下方式之一:

  • 先判 HasValueif (x.HasValue) { use(x.Value); }
  • 用空合并运算符 ?? 提供默认值: int y = x ?? 0;
  • GetValueOrdefault():返回 Valuedefault(T)(对 int? 就是 0);也可带参数 GetValueOrDefault(42)
  • 转换为非空类型时,显式强制转换(仅当确定有值):int z = (int)x; —— 这会触发隐式调用 Value,仍可能异常

数据库字段映射与 json 序列化中的典型场景

数据库里 INT NULL 列读到 C# 通常映射为 int?;JSON 反序列化时,缺失字段或 null 值也会被转成 null 的可空类型。

  • Entity Framework Core 默认将可空数据库列映射为 T?,例如 public int? Age { get; set; }
  • 使用 System.Text.Json 时,int? 能正确处理 null、数字或缺失字段;但若 JSON 中传了字符串 "abc",会反序列化失败(不是可空性问题,而是类型不匹配)
  • 注意:EF Core 的 HasDefaultValue()HasDefaultValueSql()int? 字段无效——因为默认值本身不能解决“是否允许 null”的约束,那是 IsRequired(false) 控制的

可空引用类型(C# 8+)和可空值类型不是一回事

这是最容易混淆的点:String? 是「可空引用类型」,属于编译期静态分析特性(由 #nullable enable 启用),不影响运行时行为;而 int? 是运行时真实存在的结构体类型,改变 IL 和内存布局。

  • 开启可空引用类型后,string s; 被认为「不应为 null」,编译器警告你未初始化或可能赋 null;但 string? s; 表示接受 null,不警告
  • int? 不受 #nullable 开关影响——它始终存在、始终可为 null,且运行时可检测
  • 两者共存时,变量声明如 string?[]? 表示「可为空的字符串数组,该数组本身也可为 null」,但这种嵌套极少需要,容易过度设计
int? x = null; Console.WriteLine(x?.ToString() ?? "null"); // 安全输出 "null" Console.WriteLine(x.GetValueOrDefault(-1)); // 输出 -1 int y = x ?? 42; // 等效于 GetValueOrDefault(42)

可空值类型的核心就三点:它是结构体、必须检查 HasValue 才能取值、和可空引用类型完全无关。很多人卡在第一步——以为 ?? 能解决一切,结果在 .Value 上静默崩溃。

text=ZqhQzanResources