C# 可空类型(Nullable Types)
下面是对 C# 可空类型(Nullable Types) 的全面专业讲解,信息来源于 Microsoft 官方文档、.NET 实践经验,并提供多种使用方式和实用建议。
一、什么是可空类型?
在 C# 中,值类型(如 int、bool、DateTime 等)默认不能为 null。而有时我们需要表示一个“未赋值”或“缺失”的状态,这时就可以使用 可空类型。
✅ 可空类型允许值类型变量可以存储 null 值。
二、语法定义
int? x = null; // 可空 int 类型
bool? isReady = true; // 可空 bool 类型
等价写法(使用 Nullable<T>):
Nullable<int> x = null;
三、适用于哪些类型?
- 只能用于 值类型(value types)
- 引用类型本身就可以为
null,无需可空
✅ 支持的常用值类型:
int? // Nullable<int>
double? // Nullable<double>
bool? // Nullable<bool>
DateTime? // Nullable<DateTime>
enum? // Nullable<YourEnum>
四、使用 Nullable 类型的常见操作
1. 判断是否有值
int? x = null;
if (x.HasValue)
{
Console.WriteLine(x.Value);
}
else
{
Console.WriteLine("x is null");
}
2. 获取值或默认值(Null 合并运算符 ??)
int? x = null;
int y = x ?? -1; // 如果 x 为 null,则 y = -1
3. 拆箱 nullable(Null 合并赋值 ??=)
int? number = null;
number ??= 100; // 如果 number 为 null,就赋值 100
Console.WriteLine(number); // 输出 100
4. 可空类型转换(显式/隐式)
int? x = 5;
double? d = x; // 隐式转换
五、Nullable 与条件运算符(?.)
DateTime? date = GetDateOrNull();
int? year = date?.Year;
解释:只有当 date 不为 null,才访问 Year 属性,否则结果为 null。
六、访问 Value 时的风险
int? x = null;
int y = x.Value; // ❌ 抛出 InvalidOperationException
建议用 HasValue 或 ?? 运算符处理 null 安全性。
七、Nullable 与数据库场景(ADO.NET)
SqlDataReader reader = command.ExecuteReader();
int? age = reader.IsDBNull(0) ? null : reader.GetInt32(0);
在数据库中,很多字段允许 NULL,使用 Nullable 可以无缝匹配 SQL NULL 值。
八、与结构体和枚举配合使用
enum Status { Pending, Done, Failed }
Status? taskStatus = null;
if (taskStatus == null)
{
Console.WriteLine("Status unknown.");
}
九、示例:使用 Nullable 类型进行业务逻辑判断
public decimal? GetDiscount(DateTime? birthDate)
{
if (!birthDate.HasValue)
return null;
int age = DateTime.Now.Year - birthDate.Value.Year;
return age >= 60 ? 0.1m : 0.0m;
}
十、官方参考链接
十一、最佳实践建议
| 建议 | 说明 |
|---|---|
✅ 合理使用 ?? 或 HasValue | 避免访问 .Value 时抛出异常 |
| ✅ 多用于数据库、表单等可缺省输入的数据场景 | 可读性高,表示明确意图 |
❌ 不推荐在引用类型上再用 Nullable<T> | 引用类型本身可以为 null,无需再用 Nullable 包装 |
✅ 配合 switch, if, ?., ?? 等使用 | 构建健壮的空值判断逻辑 |
十二、可空引用类型(Nullable Reference Types)[C# 8.0+]
与本文讲的 可空值类型 不同,C# 8 引入了 可空引用类型,用于增强代码的 null 安全性。
启用后,可以使用:
string? name = null; // 明确表示 name 可为 null
详情文档请见:
更多详细内容,请关注其他相关文章!