空值条件与空值合并运算符
组合使用 ?、?[]、?? 和 ??=,编写简洁且空值安全的代码,避免冗长的空值检查。
空值条件与空值合并运算符 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
空值安全代码模式
C# 提供了三个专门用于简洁处理空值的运算符:空值条件运算符(?.、?[])、空值合并运算符(??)以及空值合并赋值运算符(??=)。它们结合使用,可以消除大多数冗长的空值检查样板代码。
空值条件运算符:?.
如果左侧为空值,?. 会短路并返回 null,而不是抛出 NullReferenceException。结果类型会变为可空类型。
User? user = GetUser(id);
// Without ?.:
string? name = null;
if (user != null) name = user.Name;
// With ?.:
string? name2 = user?.Name;
// Chained:
string? city = user?.Address?.City;
// Method call:
string? upper = user?.Name?.ToUpper();带索引访问器的空值条件运算符:?[]
?[] 是空值条件索引运算符。当数组或集合本身可能为空时,它可以安全地访问其中的元素。
List<string>? tags = product?.Tags;
// Safe index access
string? firstTag = tags?[0];
// Null-conditional LINQ
int? count = tags?.Count;
bool? hasItems = tags?.Any();
// With methods:
string? joined = tags?.FirstOrDefault()?.ToUpper();空值合并运算符:??
如果左操作数不为空,?? 就返回左操作数;否则返回右操作数(回退值)。它是 x != null ? x : fallback 的简洁替代写法。
string? name = GetName();
// Without ??:
string display = name != null ? name : "Anonymous";
// With ??:
string display2 = name ?? "Anonymous";
// Chaining ?? for multiple fallbacks:
string result = primary ?? secondary ?? tertiary ?? "Default";
// Combining with ?.
string city = user?.Address?.City ?? "Unknown City";空值合并赋值:??=
??= 仅当变量当前为 null 时,才会将右侧的值赋给该变量。它非常适合用于延迟初始化模式。
// Lazy initialization
private List<string>? _cache;
public List<string> GetCache()
{
_cache ??= new List<string>(); // only assigns if null
return _cache;
}
// Equivalent to:
// if (_cache is null) _cache = new List<string>();
// In-place:
string? name = null;
name ??= "Default";
Console.WriteLine(name); // "Default"在事件中使用 ?.
空值条件运算符是调用事件的标准线程安全方式,可避免先单独进行 null 检查、再调用事件所产生的竞争条件。
public event EventHandler<DataEventArgs>? DataReceived;
// Thread-safe event invocation:
DataReceived?.Invoke(this, new DataEventArgs(data));
// This is equivalent to:
var handler = DataReceived;
if (handler != null) handler(this, new DataEventArgs(data));
// (local copy avoids race condition between check and invoke)复杂链式示例
组合使用这些运算符,可以简洁、易读且安全地遍历深层嵌套的对象图,同时避免 null。
var order = GetOrder(id);
// Deeply nested with fallbacks:
string countryCode = order
?.Customer
?.ShippingAddress
?.Country
?.Code
?? "US";
// Collection safe access:
decimal firstLineTotal = order
?.Lines
?.FirstOrDefault()
?.Total
?? 0m;
// Method chain:
string? trackingUpper = order?.TrackingNumber?.ToUpper().Trim();LINQ 中的空值条件运算符
空值条件运算符可以与 LINQ 无缝协作,从而安全地查询可能为 null 的集合或属性。
List<Order>? orders = customer?.Orders;
// Safe LINQ on a nullable collection:
var totalRevenue = orders?.Sum(o => o.Total) ?? 0m;
var pendingCount = orders?.Count(o => o.Status == OrderStatus.Pending) ?? 0;
var latest = orders?.MaxBy(o => o.PlacedAt)?.Id;使用 ThrowIfNull 进行空值保护
对于不允许为 null 的参数,请使用 ArgumentNullException.ThrowIfNull()(.NET 6+),在方法入口处以简洁且清晰的方式完成验证。
public void ProcessOrder(Order order, Customer customer)
{
ArgumentNullException.ThrowIfNull(order);
ArgumentNullException.ThrowIfNull(customer);
// From this point, compiler knows both are non-null
Console.WriteLine(order.Id);
Console.WriteLine(customer.Name);
}
// .NET 7+: ArgumentException.ThrowIfNullOrEmpty
void Save(string name)
{
ArgumentException.ThrowIfNullOrWhiteSpace(name);
// name is guaranteed non-empty
}Switch 中的非空模式
使用 is not null 和 is { } 进行模式匹配,可以构建简洁的 null 检查模式,尤其适用于 switch 表达式。
string Describe(object? obj) => obj switch
{
null => "nothing",
string s when s.Length == 0 => "empty string",
string s => $"string: {s}",
int i => $"integer: {i}",
{ } => $"object: {obj.GetType().Name}"
};
// is not null in if statements:
if (order is not null && order.Customer is { Name: var name })
Console.WriteLine(name);快速检查
当 user 为 null 时,表达式 user?.Name ?? "Anonymous" 会返回什么?
总结:空值条件与空值合并
关键要点:
?.:安全的成员访问——接收对象为 null 时返回 null,而不是抛出异常?[]:安全地访问可能为 null 的集合中的索引??:左操作数为 null 时使用回退值??=:仅在值为 null 时赋值——非常适合延迟初始化- 将它们串联起来:使用
a?.B?.C ?? defaultVal深入遍历对象,同时安全处理 null - 使用
ArgumentNullException.ThrowIfNull()为参数添加验证保护
常见问题解答
「空值条件与空值合并运算符」课时是免费的吗?
是的 — 「空值条件与空值合并运算符」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「空值条件与空值合并运算符」这节课中我会学到什么?
组合使用 ?、?[]、?? 和 ??=,编写简洁且空值安全的代码,避免冗长的空值检查。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「空值条件与空值合并运算符」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 启用并理解 NRT
- 注解:?、!、MaybeNull 与 NotNull
- 空值条件与空值合并运算符
- 将代码库迁移到 NRT