C# 可空类型

`int?`、`Nullable<T>`、可空引用类型、以及 `?.`/`??` 组合。

Intermediate
Key Points值类型的 `?` 是 `Nullable<T>`;引用类型的 `?` 是编译器的空值检查标记。

值类型可空

C#
int? a = null;
int? b = 5;

Console.WriteLine(a.HasValue);
Console.WriteLine(b.HasValue);
Console.WriteLine(a.GetValueOrDefault());
Console.WriteLine(b.GetValueOrDefault(99));
Console.WriteLine(a ?? 0);

// 运算会传播 null
Console.WriteLine(a + 1 == null);

// 与普通 int 不能直接混算
// int c = a + 1;      // 编译错误
int d = (a ?? 0) + 1;
Console.WriteLine(d);
Output
False
True
0
5
0
True
1

可空引用类型

C#
#nullable enable

string notNull = "一定不是 null";
string? maybeNull = null;

Console.WriteLine(notNull.Length);
Console.WriteLine(maybeNull?.Length);

// 编译器会警告:maybeNull 可能为 null
// Console.WriteLine(maybeNull.Length);

// 确定不为 null 时用 !
Console.WriteLine(maybeNull!.Length);
Output
15

string? and string are identical at runtime; the difference is compile time: string? means "may be null, check before use". It is on by default for new .NET 6+ projects.

Nullable reference types produce warnings, not errors. But the flagged spots are exactly where NullReferenceException comes from in production. Enable Nullable and treat those warnings as errors.

安全访问的三件套

C#
string? name = null;

// 1. ?. 短路
Console.WriteLine(name?.ToUpper() ?? "(空)");

// 2. ?? 提供默认值
Console.WriteLine(name ?? "匿名");

// 3. ?[] 索引
int[]? arr = null;
Console.WriteLine(arr?[0] ?? -1);

// 组合
var len = name?.Trim().Length ?? 0;
Console.WriteLine(len);
Output
(空)
匿名
-1
0

常见场景

C#
class User
{
    public string? Nickname { get; set; }
    public Address? Address { get; set; }
}

class Address
{
    public string City { get; set; } = "";
}

var u = new User();

// 深层访问,任何一环为 null 都不会炸
var city = u.Address?.City ?? "未知";
Console.WriteLine(city);

// 想区分「没地址」和「城市为空」
if (u.Address is null)
{
    Console.WriteLine("没有地址信息");
}
else
{
    Console.WriteLine($"城市:{u.Address.City}");
}
Output
未知
没有地址信息

Use ?. when a default will do, is null when the cases differ. Do not mix them: if (u.Address?.City != null) conflates "no address" with "empty city".

可空与数据库

C#
// 数据库里的 NULL 列对应可空类型
class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal? Discount { get; set; }        // 可能没有折扣
    public DateTime? DeletedAt { get; set; }      // 软删除
}

var p = new Product { Id = 1, Name = "键盘" };
var price = 199m;
var final = price * (1 - (p.Discount ?? 0));
Console.WriteLine(final);
Console.WriteLine(p.DeletedAt is null);
Output
199
True

Friends & Partners