目录

8. ? 与 ?? (Null 处理与条件逻辑)

在 C# 中,`?` 和 `??` 运算符主要用于处理 null 值(空值) 以及 条件逻辑。它们不仅能简化代码,还能显著提高代码的可读性和安全性(防止空引用异常)。

8.1. ? 运算符 (单问号)

`?` 符号在 C# 中有三种截然不同的用法,取决于上下文。

8.1.1 可空类型修饰符 (Nullable Type Modifier)

用于定义一个值类型(如 `int`, `double`, `bool`, `DateTime` 等)可以存储 `null`。

int  a = 10;    // 正常 int,不能赋值 null
int? b = null;  // 可空 int,可以赋值 null
 
if (b.HasValue) 
{
    Console.WriteLine(b.Value);
}

8.1.2 三元条件运算符 (Ternary Conditional Operator)

这是 `if-else` 语句的简写形式,用于根据布尔表达式返回两个值中的一个。

int x = 10;
string result = (x > 5) ? "大于5" : "小于等于5";

8.1.3 Null 条件运算符 (Null-conditional Operator)

(C# 6.0+) 也称为“安全导航运算符”。用于在访问成员(属性、方法)或索引器之前检查对象是否为 `null`。

string text = null;
// length 将会是 null (int?),而不是抛出异常
int? length = text?.Length; 
 
// 链式调用
Person person = null;
string city = person?.Address?.City; // 如果 person 或 Address 为 null,city 为 null

8.2. ?? 运算符 (双问号)

`??` 系列运算符主要用于处理 null 时的默认值逻辑。

8.2.1 Null 合并运算符 (Null-coalescing Operator)

用于判断左侧的操作数是否为 `null`。

string input = null;
// 如果 input 是 null,则 name 变成 "DefaultName"
string name = input ?? "DefaultName"; 

8.2.2 Null 合并赋值运算符 (Null-coalescing Assignment Operator)

(C# 8.0+) 这是 `??` 和 `=` 的组合。

List<int> numbers = null;
 
// 因为 numbers 是 null,所以会初始化新列表
numbers ??= new List<int>(); 
 
// 此时 numbers 已不是 null,这行代码不会执行任何操作
numbers ??= new List<int>(); 

8.3. 综合代码示例

以下示例展示了如何在一个场景中混合使用上述运算符。

using System;
using System.Collections.Generic;
 
public class Program
{
    public static void Main()
    {
        // 1. 可空类型修饰符 (?)
        int? nullableInt = null;
 
        // 2. Null 合并运算符 (??)
        // 如果 nullableInt 是 null,则使用默认值 0
        int finalValue = nullableInt ?? 0; 
        Console.WriteLine($"1. Null合并结果: {finalValue}"); // 输出: 0
 
        // 3. 三元运算符 (?:)
        string status = (finalValue > 5) ? "High" : "Low";
        Console.WriteLine($"2. 三元运算结果: {status}"); // 输出: Low
 
        // 4. Null 条件运算符 (?.)
        Person person = null;
        // 如果 person 为 null,name 直接为 null,不会报错
        string name = person?.Name; 
        Console.WriteLine($"3. Null条件访问: '{name}'"); // 输出: '' (空)
 
        // 组合使用:安全访问 + 默认值
        // 如果 person 为 null 或者 Name 为 null,则显示 "Unknown"
        string displayName = person?.Name ?? "Unknown";
        Console.WriteLine($"4. 组合使用结果: {displayName}"); // 输出: Unknown
 
        // 5. Null 合并赋值运算符 (??=)
        List<string> tags = null;
 
        // 因为 tags 是 null,所以进行赋值
        tags ??= new List<string>(); 
        tags.Add("C#");
 
        Console.WriteLine($"5. 列表元素数量: {tags.Count}"); // 输出: 1
    }
}
 
public class Person
{
    public string Name { get; set; }
}

8.4. 总结表

运算符 名称 语法示例 解释
`?` 可空类型修饰符 `int? x` 允许值类型为 null。
`?:` 三元运算符 `a ? b : c` 如果 a 为真选 b,否则选 c。
`?.` Null 条件运算符 `obj?.Prop` 如果 obj 非空则访问 Prop,否则返回 null。
`??` Null 合并运算符 `a ?? b` 如果 a 非空返回 a,否则返回 b (默认值)。
`??=` Null 合并赋值 `a ??= b` 仅当 a 为 null 时,将 b 赋值给 a。