C# 可空类型(Nullable)详解

📅 2026/7/7 18:43:22 👁️ 阅读次数 📝 编程学习
C# 可空类型(Nullable)详解

在 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)获取值或指定默认值
??空合并运算符,提供默认值
??=空合并赋值,仅在为空时赋值
?.空条件运算符,避免空引用异常