C# 可空类型(Nullable)详解
📅 2026/7/7 18:43:22
👁️ 阅读次数
📝 编程学习
在 C# 中,**可空类型(Nullable Types)允许值类型(Value Types)**存储null值。在数据库开发、Web 开发以及企业级应用中非常常见。
一、为什么需要可空类型?
普通值类型不能为null。
例如:
int age = null; // ❌ 编译错误因为:
- int
- double
- bool
- DateTime
都属于值类型,它们必须有一个值。
但是现实开发中,经常会出现:
- 用户年龄未知
- 出生日期未知
- 成绩未录入
这些情况都需要一个"没有值"的状态。
因此 C# 提供了 Nullable。
二、Nullable 的写法
有两种写法。
第一种(完整写法)
Nullable<int> age = null;等价于
Nullable<int> age = 18;第二种(推荐)
使用?
int? age = null;其实就是:
Nullable<int>的语法糖。
例如:
double? price = null; bool? result = null; DateTime? birthday = null;三、示例
using System; class Program { static void Main() { int? age = null; Console.WriteLine(age); } }输出
什么也没有,因为值就是 null。
再赋值:
int? age = 20; Console.WriteLine(age);输出
20四、HasValue 属性
判断是否有值。
int? age = null; Console.WriteLine(age.HasValue);输出
False再看:
int? age = 25; Console.WriteLine(age.HasValue);输出
True五、Value 属性
获取真正的值。
int? age = 25; Console.WriteLine(age.Value);输出
25但是:
int? age = null; Console.WriteLine(age.Value);运行结果:
System.InvalidOperationException Nullable object must have a value.所以:
不要在 HasValue 为 false 时访问 Value。
正确写法:
if (age.HasValue) { Console.WriteLine(age.Value); }六、GetValueOrDefault()
获取值。
如果为空,就返回默认值。
int? age = null; Console.WriteLine(age.GetValueOrDefault());输出
0因为 int 默认值就是 0。
也可以指定默认值:
Console.WriteLine(age.GetValueOrDefault(18));输出
18七、空合并运算符 ??
这是 Nullable 最常用的功能。
int? age = null; Console.WriteLine(age ?? 18);输出
18意思:
如果左边不是 null:
返回左边如果左边是 null:
返回右边例如:
int? age = 30; Console.WriteLine(age ?? 18);输出
30八、空合并赋值 ??=
C# 8.0 新增。
例如:
string name = null; name ??= "Tom"; Console.WriteLine(name);输出
Tom如果已经有值:
string name = "Jack"; name ??= "Tom"; Console.WriteLine(name);输出
Jack不会覆盖。
九、空条件运算符 ?.
用于防止空引用异常。
例如:
Student stu = null; Console.WriteLine(stu?.Name);不会报错。
输出
null如果不用:
Console.WriteLine(stu.Name);就会:
NullReferenceException十、可空类型之间运算
int? a = 10; int? b = 20; Console.WriteLine(a + b);输出
30如果其中一个是 null:
int? a = null; int? b = 20; Console.WriteLine(a + b);输出
结果也是 null。
因为:
null + 20 = null十一、判断是否为空
最简单:
if (age == null) { Console.WriteLine("没有年龄"); }或者:
if (age != null) { Console.WriteLine(age); }也可以:
if (age.HasValue) { Console.WriteLine(age.Value); }十二、Nullable<T> 常用成员
| 成员 | 作用 |
|---|---|
| HasValue | 是否有值 |
| Value | 获取值 |
| GetValueOrDefault() | 获取值,没有则返回默认值 |
| GetValueOrDefault(x) | 没有值返回指定值 |
十三、值类型与引用类型
| 类型 | 是否可为 null |
|---|---|
| int | ❌ |
| double | ❌ |
| bool | ❌ |
| DateTime | ❌ |
| int? | ✅ |
| double? | ✅ |
| bool? | ✅ |
| DateTime? | ✅ |
| string | ✅(引用类型) |
| object | ✅(引用类型) |
补充(C# 8.0+):虽然
string本身可以为null,但启用**可空引用类型(Nullable Reference Types)**后,可以用string?明确表示允许为null,而string表示不应为null,编译器会提供相应的空值警告。这与int?(可空值类型)是不同的概念。
十四、实际开发案例
假设数据库中的年龄字段允许为空:
public class User { public string Name { get; set; } public int? Age { get; set; } }使用:
User user = new User(); user.Name = "张三"; user.Age = null; Console.WriteLine(user.Age ?? 18);输出
18表示:
如果数据库没有年龄,就默认显示 18。
十五、最佳实践
- 优先使用
T?(如int?、DateTime?),代码更简洁。 - 读取值前先判断
HasValue,或使用??提供默认值,避免直接访问Value。 - 数据库字段可为空时,实体类对应属性应使用可空值类型。
- 区分两类可空:
int?:可空值类型(Nullable<int>)。string?:可空引用类型(C# 8.0+ 的编译器空值分析)。
十六、小结
| 语法 | 说明 |
|---|---|
int? age | 声明可空整型 |
Nullable<int> | int?的完整写法 |
HasValue | 判断是否有值 |
Value | 获取值(需确保不为null) |
GetValueOrDefault() | 获取值或类型默认值 |
GetValueOrDefault(x) | 获取值或指定默认值 |
?? | 空合并运算符,提供默认值 |
??= | 空合并赋值,仅在为空时赋值 |
?. | 空条件运算符,避免空引用异常 |
编程学习
技术分享
实战经验