Skip to content

C# switch 语句:从传统分支到模式匹配的艺术 ​

引言:代码世界的「分类器」 ​

想象你走进一家奶茶店,店员问:「需要什么口味?」你回答「原味」「抹茶」或「巧克力」——店员根据这个精确值,直接执行对应的制作流程。这就是 switch 语句的原型:不是「大于 18 岁」这样的范围判断,而是「周一」「周二」「周三」这样的离散值匹配。

switch 语句是 C# 中处理多路分支的核心结构。与 if-else 的「条件判断」不同,switch 擅长「值匹配」——把一个变量的值与多个候选值逐一比对,命中后执行对应分支。随着 C# 版本的演进,switch 从简单的数值匹配,进化为支持模式匹配的强大工具,甚至成为函数式编程风格的重要载体。


一、基础定义与核心作用 ​

1.1 什么是 switch 语句 ​

switch 语句是一种选择结构,根据表达式的值,从多个候选分支中选择其一执行。它解决的核心问题是:当同一个变量需要与多个离散值比较时,避免冗长的 if-else-if 链。

csharp
// if-else 链:冗长且重复
int day = 3;
if (day == 1) Console.WriteLine("周一");
else if (day == 2) Console.WriteLine("周二");
else if (day == 3) Console.WriteLine("周三");
else if (day == 4) Console.WriteLine("周四");
else Console.WriteLine("其他");

// switch 语句:简洁清晰
switch (day)
{
    case 1: Console.WriteLine("周一"); break;
    case 2: Console.WriteLine("周二"); break;
    case 3: Console.WriteLine("周三"); break;
    case 4: Console.WriteLine("周四"); break;
    default: Console.WriteLine("其他"); break;
}

1.2 核心作用 ​

  • 消除重复:避免反复书写 else if (x == ...)
  • 提升可读性:分支结构一目了然,意图明确
  • 编译器优化:某些场景下编译器可生成跳转表,性能优于链式判断
  • 模式匹配:C# 7.0+ 后,switch 成为模式匹配的主战场

二、基础语法格式详解 ​

2.1 传统 switch 语句的完整结构 ​

csharp
switch (表达式)           // switch 表达式:要匹配的值
{
    case 常量1:           // case 标签:候选匹配值
        语句块1;          // 命中后执行的代码
        break;            // 终止当前分支(C# 中必须)

    case 常量2:
        语句块2;
        break;

    case 常量3:           // 多个 case 共享同一代码块(fall-through)
    case 常量4:
        语句块3;
        break;

    default:              // 默认分支:所有 case 都不命中时执行
        默认语句块;
        break;
}

语法要点:

要素说明
switch 表达式支持 int、char、string、enum、bool 及可空类型
case 标签必须是编译时常量(字面量、const 变量、枚举成员)
breakC# 强制要求每个分支以 break、return、throw 或 goto 结束
default可选,通常放最后;不命中任何 case 时执行
fall-throughC# 禁止隐式贯穿,但允许多个 case 标签共享同一代码块

2.2 完整的可运行示例 ​

csharp
// 场景:根据星期几输出课程安排
int dayOfWeek = 3;

switch (dayOfWeek)
{
    case 1:  // 周一
        Console.WriteLine("周一:数学 + 英语");
        break;
    case 2:  // 周二
        Console.WriteLine("周二:物理 + 化学");
        break;
    case 3:  // 周三
    case 4:  // 周四(与周三课程相同)
        Console.WriteLine("周三/四:体育课 + 自习");
        break;
    case 5:  // 周五
        Console.WriteLine("周五:班会 + 大扫除");
        break;
    case 6:  // 周六
    case 7:  // 周日
        Console.WriteLine("周末:休息");
        break;
    default: // 非法输入
        Console.WriteLine("无效星期值");
        break;
}

// 输出:周三/四:体育课 + 自习

2.3 枚举类型:switch 的最佳搭档 ​

csharp
enum Color { Red, Green, Blue }

Color favorite = Color.Green;

switch (favorite)
{
    case Color.Red:
        Console.WriteLine("红色:热情");
        break;
    case Color.Green:
        Console.WriteLine("绿色:自然");
        break;
    case Color.Blue:
        Console.WriteLine("蓝色:冷静");
        break;
    // 枚举的 default 是可选的,因为编译器会检查穷尽性
}

// 输出:绿色:自然

2.4 字符串匹配:区分大小写的细节 ​

csharp
string command = "start";

switch (command.ToLower())  // 统一转为小写,避免大小写问题
{
    case "start":
        Console.WriteLine("启动服务");
        break;
    case "stop":
        Console.WriteLine("停止服务");
        break;
    case "restart":
        Console.WriteLine("重启服务");
        break;
    default:
        Console.WriteLine("未知命令");
        break;
}

三、版本演进:从传统到现代 ​

3.1 C# 7.0:模式匹配的萌芽 ​

C# 7.0 在 switch 中引入了类型模式和 when 守卫,打破了「只能匹配常量」的限制。

csharp
object obj = "Hello";

switch (obj)
{
    case int i:                    // 类型模式:匹配 int 类型
        Console.WriteLine($"整数:{i}");
        break;
    case string s when s.Length > 5:  // when 守卫:附加条件
        Console.WriteLine($"长字符串:{s}");
        break;
    case string s:                 // 无守卫的类型模式
        Console.WriteLine($"短字符串:{s}");
        break;
    case null:                     // null 模式
        Console.WriteLine("空引用");
        break;
    default:
        Console.WriteLine("其他类型");
        break;
}

// 输出:短字符串:Hello

3.2 C# 8.0:switch 表达式(Switch Expression) ​

革命性变化:switch 从「语句」进化为「表达式」,有返回值,语法更简洁。

csharp
// 传统 switch 语句:需要 break,无返回值
string GetGrade(int score)
{
    string grade;
    switch (score / 10)
    {
        case 10:
        case 9:
            grade = "A";
            break;
        case 8:
            grade = "B";
            break;
        case 7:
            grade = "C";
            break;
        default:
            grade = "D";
            break;
    }
    return grade;
}

// C# 8.0 switch 表达式:有返回值,箭头语法
string GetGradeModern(int score) => (score / 10) switch
{
    10 => "A",      // 模式 => 表达式,无需 break
    9 => "A",
    8 => "B",
    7 => "C",
    _ => "D"        // _ 表示默认(弃元模式)
};

// 更简洁:直接在赋值中使用
int score = 85;
string grade = (score / 10) switch
{
    10 or 9 => "优秀",    // C# 9.0 的 or 模式
    8 => "良好",
    7 => "及格",
    _ => "不及格"
};

switch 表达式语法要点:

  • 使用 => 箭头替代 case: 和 break
  • 每个分支是「模式 => 结果表达式」
  • _ 是弃元模式,表示「匹配任何值」,相当于 default
  • 编译器强制要求穷尽匹配(exhaustiveness),否则编译警告

3.3 C# 9.0:模式匹配增强 ​

C# 9.0 引入了关系模式、逻辑模式、类型模式简化等。

csharp
int age = 25;

string category = age switch
{
    < 0 => "非法年龄",           // 关系模式:小于
    >= 0 and < 18 => "未成年",   // 逻辑模式:and 组合
    >= 18 and < 60 => "成年人",
    >= 60 => "老年人"
};

// 逻辑模式:or、and、not
bool IsWorkingAge(int a) => a is >= 18 and <= 65;

// 类型模式简化:省略变量声明(当不需要使用变量时)
object obj = 42;
string desc = obj switch
{
    int => "是整数",             // 无需 case int i
    string => "是字符串",
    _ => "其他类型"
};

3.4 C# 10.0+:后续优化 ​

  • C# 10:扩展了 or 模式的组合能力,支持更复杂的嵌套模式
  • C# 11:list 模式(列表模式),支持数组/集合的匹配
  • C# 12:主构造函数中更灵活的 switch 使用
csharp
// C# 11 列表模式(预览)
int[] numbers = { 1, 2, 3 };

string result = numbers switch
{
    [] => "空数组",
    [1] => "只有 1",
    [1, 2] => "1 和 2",
    [1, ..] => "以 1 开头",      // .. 表示剩余元素
    [.., 3] => "以 3 结尾",
    _ => "其他"
};

四、模式匹配详解 ​

4.1 常量模式(Constant Pattern) ​

最基础的匹配:与常量值比较。

csharp
object obj = 42;

string result = obj switch
{
    0 => "零",
    42 => "答案",
    -1 => "负数",
    _ => "其他"
};

// 输出:答案

支持的常量类型:int、long、char、string、bool、枚举、decimal、double、float(注意浮点精度问题)。

4.2 类型模式(Type Pattern) ​

匹配类型:判断对象是否属于某个类型。

csharp
object[] items = { 1, "hello", 3.14, true, null };

foreach (var item in items)
{
    string desc = item switch
    {
        int i => $"整数:{i}(平方={i * i})",
        string s => $"字符串:{s}(长度={s.Length})",
        double d => $"浮点数:{d:F2}",
        bool b => $"布尔:{b}",
        null => "空引用",
        _ => "未知类型"
    };
    Console.WriteLine(desc);
}

// 输出:
// 整数:1(平方=1)
// 字符串:hello(长度=5)
// 浮点数:3.14
// 布尔:True
// 空引用

4.3 关系模式(Relational Pattern)— C# 9.0+ ​

比较匹配:>, <, >=, <=。

csharp
double temperature = 22.5;

string weather = temperature switch
{
    < -10 => "严寒",
    >= -10 and < 0 => "寒冷",
    >= 0 and < 15 => "凉爽",
    >= 15 and < 25 => "温暖",
    >= 25 and < 35 => "炎热",
    >= 35 => "酷暑"
};

// 输出:温暖

4.4 逻辑模式(Logical Pattern)— C# 9.0+ ​

组合匹配:and(且)、or(或)、not(非)。

csharp
int month = 7;

string season = month switch
{
    >= 3 and <= 5 => "春季",
    >= 6 and <= 8 => "夏季",
    >= 9 and <= 11 => "秋季",
    12 or 1 or 2 => "冬季",
    _ => "非法月份"
};

// not 模式:排除特定情况
bool IsNotWeekend(DayOfWeek day) => day is not (DayOfWeek.Saturday or DayOfWeek.Sunday);

// 输出:夏季

4.5 属性模式(Property Pattern) ​

匹配对象的属性值:无需先类型转换再判断属性。

csharp
record Person(string Name, int Age, bool IsVip);

Person[] people =
{
    new("张三", 25, true),
    new("李四", 17, false),
    new("王五", 30, true),
    new("赵六", 65, false)
};

foreach (var p in people)
{
    string level = p switch
    {
        // 属性模式:匹配 Age >= 60 且 IsVip 为 true
        { Age: >= 60, IsVip: true } => "尊贵长者",
        { Age: >= 60 } => "普通长者",
        { IsVip: true } => "VIP 客户",
        { Age: < 18 } => "未成年",
        _ => "普通客户"
    };
    Console.WriteLine($"{p.Name}:{level}");
}

// 输出:
// 张三:VIP 客户
// 李四:未成年
// 王五:VIP 客户
// 赵六:普通长者

嵌套属性模式:

csharp
record Address(string City, string ZipCode);
record User(string Name, Address Addr);

User user = new("小明", new Address("北京", "100000"));

string region = user switch
{
    { Addr: { City: "北京" or "上海" } } => "一线城市",
    { Addr: { City: "广州" } } => "一线城市",
    _ => "其他城市"
};

4.6 位置模式(Positional Pattern) ​

基于解构的匹配:适用于 record 或支持 Deconstruct 的类型。

csharp
record Point(int X, int Y);

Point[] points = { new(0, 0), new(1, 0), new(0, 1), new(1, 1), new(5, 5) };

foreach (var p in points)
{
    string location = p switch
    {
        (0, 0) => "原点",                    // 位置模式:匹配 X=0, Y=0
        (0, _) => "Y 轴上",                  // _ 表示任意 Y
        (_, 0) => "X 轴上",                  // _ 表示任意 X
        (var x, var y) when x == y => "对角线", // 带 when 的位置模式
        _ => "普通位置"
    };
    Console.WriteLine($"({p.X}, {p.Y}):{location}");
}

// 输出:
// (0, 0):原点
// (1, 0):X 轴上
// (0, 1):Y 轴上
// (1, 1):对角线
// (5, 5):对角线

4.7 组合示例:复杂业务规则 ​

csharp
record Order(int Id, string Status, decimal Amount, bool IsPaid, DateTime CreateTime);

string GetOrderAction(Order order) => order switch
{
    // 未支付且金额大于 1000 的待处理订单
    { Status: "Pending", IsPaid: false, Amount: > 1000 } => "需要人工审核",

    // 已支付但超过 7 天未发货
    { IsPaid: true, CreateTime: var t } when (DateTime.Now - t).Days > 7 => "催发货",

    // 已取消的订单
    { Status: "Cancelled" } => "已关闭",

    // 小额待支付订单(位置模式 + 属性模式)
    { Status: "Pending", IsPaid: false, Amount: <= 1000 } => "自动提醒",

    _ => "正常处理"
};

五、实战注意事项 ​

5.1 覆盖性检查与穷尽匹配 ​

传统 switch 语句:编译器不强制穷尽匹配,default 是可选的。

csharp
enum Color { Red, Green, Blue }

Color c = Color.Red;

// 传统 switch:不写 default 也能编译,但运行时不匹配就跳过
switch (c)
{
    case Color.Red:
        Console.WriteLine("红");
        break;
    // 没有处理 Green 和 Blue,编译通过但可能漏处理
}

switch 表达式:编译器强制要求穷尽匹配,否则会警告。

csharp
// ❌ 编译警告:CS8509:switch 表达式未处理所有可能值
string name = c switch
{
    Color.Red => "红色"
    // 缺少 Green、Blue 和 default(_)
};

// ✅ 正确:添加弃元模式处理所有剩余情况
string name2 = c switch
{
    Color.Red => "红色",
    Color.Green => "绿色",
    Color.Blue => "蓝色",
    _ => "未知"  // 必须处理所有情况
};

5.2 Fall-through 规则的历史变化 ​

版本规则
C/C++允许隐式贯穿(fall-through),不加 break 会继续执行下一个 case
C# 1.0-6.0禁止隐式贯穿,但允许多个 case 标签共享同一代码块
C# 7.0+引入 when 守卫,守卫失败时不会贯穿到下一个 case
C# 8.0+switch 表达式彻底消除贯穿概念,每个分支独立
csharp
// C/C++ 风格(C# 不支持!)
// case 1:
//     Console.WriteLine("一");
//     // 没有 break,会贯穿到 case 2
// case 2:
//     Console.WriteLine("二");
//     break;

// C# 的正确共享方式:多个 case 标签连续排列
int value = 1;
switch (value)
{
    case 1:
    case 2:
    case 3:
        Console.WriteLine("一、二或三");  // 1、2、3 都会执行这里
        break;
    default:
        Console.WriteLine("其他");
        break;
}

5.3 性能对比 ​

场景性能特点
少量分支(<5)if-else 与 switch 性能相当
大量分支(>10)switch 可能生成跳转表,性能更优
字符串匹配switch 使用哈希或字典查找,优于链式 if-else
模式匹配略低于常量匹配,但代码可读性收益远大于性能损失

实测建议:除非在极端性能敏感场景(如每秒百万次调用),否则优先选择可读性更好的方案。

5.4 switch vs if-else 选型判断 ​

csharp
// 场景1:精确值匹配(枚举、常量)→ 优先 switch
enum Status { Active, Inactive, Pending }

string GetMessage(Status s) => s switch  // ✅ 推荐
{
    Status.Active => "活跃",
    Status.Inactive => "停用",
    Status.Pending => "待审核",
    _ => "未知"
};

// 场景2:范围判断 → 必须 if-else(或 switch 表达式的关系模式)
int score = 85;

// if-else:自然直观
if (score >= 90) Console.WriteLine("A");
else if (score >= 80) Console.WriteLine("B");

// switch 表达式:同样可行,但关系模式略繁琐
string grade = score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 60 => "C",
    _ => "D"
};

// 场景3:复杂对象判断 → switch 表达式 + 属性模式(更优雅)
// 场景4:简单布尔判断 → if 语句(无需 switch)

5.5 常见坑点与规避 ​

坑点1:浮点数匹配的精度问题

csharp
double x = 0.1 + 0.2;

// ❌ 危险:浮点数不能精确匹配
string result = x switch
{
    0.3 => "等于 0.3",
    _ => "不等于 0.3"
};
// 实际输出:不等于 0.3(因为 0.1+0.2 = 0.30000000000000004)

// ✅ 规避:使用范围或阈值
string safe = x switch
{
    >= 0.299 and <= 0.301 => "约等于 0.3",
    _ => "其他"
};

坑点2:字符串匹配的 null 值

csharp
string input = null;

// ❌ 传统 switch:null 会进入 default(如果无 default 则跳过)
switch (input)
{
    case "a": Console.WriteLine("A"); break;
    default: Console.WriteLine("默认或 null"); break;
}

// ❌ switch 表达式:null 会匹配 _,但可能不是预期
string r = input switch
{
    "a" => "A",
    _ => "默认"  // null 也走这里
};

// ✅ 明确处理 null
string safe = input switch
{
    null => "空引用",
    "a" => "A",
    _ => "默认"
};

坑点3:when 守卫中的副作用

csharp
int counter = 0;

// ❌ 危险:when 中修改状态,导致逻辑混乱
string Check(int x) => x switch
{
    > 0 when counter++ > 0 => "正数",  // 副作用!每次调用 counter 都变
    _ => "其他"
};

// ✅ 规避:when 中只做纯判断,不修改状态
bool IsPositive(int x) => x > 0;
string SafeCheck(int x) => x switch
{
    _ when IsPositive(x) => "正数",
    _ => "其他"
};

六、综合实战案例:订单状态处理系统 ​

业务场景 ​

电商系统需要根据订单状态执行不同操作:

  • 待支付:超时自动取消,支持手动支付
  • 已支付:安排发货,超时提醒
  • 已发货:物流跟踪,确认收货
  • 已完成:评价邀请,售后申请
  • 已取消:退款处理,库存回补

完整实现 ​

csharp
using System;

// 订单状态枚举
public enum OrderStatus
{
    Pending,      // 待支付
    Paid,         // 已支付
    Shipped,      // 已发货
    Completed,    // 已完成
    Cancelled     // 已取消
}

// 订单记录(C# 9.0 record)
public record Order(
    int Id,
    OrderStatus Status,
    decimal Amount,
    DateTime CreateTime,
    DateTime? PayTime,
    bool IsVipCustomer
);

// 处理结果
public record ProcessResult(string Action, string Message, bool NeedNotify);

public class OrderProcessor
{
    // 核心方法:使用 switch 表达式处理订单
    public ProcessResult ProcessOrder(Order order) => order switch
    {
        // ========== 待支付订单 ==========
        // 属性模式 + 关系模式 + 逻辑模式
        { Status: OrderStatus.Pending, Amount: > 10000 } =>
            new("审核", $"订单 {order.Id} 金额过大({order.Amount:C}),需人工审核", true),

        { Status: OrderStatus.Pending, IsVipCustomer: true } =>
            new("提醒", $"VIP 订单 {order.Id} 待支付,发送专属提醒", true),

        { Status: OrderStatus.Pending, CreateTime: var t } when IsExpired(t) =>
            new("取消", $"订单 {order.Id} 已超时(创建时间:{t:MM-dd HH:mm}),自动取消", false),

        { Status: OrderStatus.Pending } =>
            new("等待", $"订单 {order.Id} 待支付,等待用户操作", false),

        // ========== 已支付订单 ==========
        // 位置模式:解构 PayTime 判断发货时效
        { Status: OrderStatus.Paid, PayTime: var pt } when IsShippingOverdue(pt) =>
            new("催发货", $"订单 {order.Id} 支付后超 48 小时未发货", true),

        { Status: OrderStatus.Paid, Amount: > 5000 } =>
            new("优先发货", $"大额订单 {order.Id},安排优先发货", true),

        { Status: OrderStatus.Paid } =>
            new("发货", $"订单 {order.Id} 正常发货流程", false),

        // ========== 已发货订单 ==========
        { Status: OrderStatus.Shipped, CreateTime: var t } when (DateTime.Now - t).Days > 30 =>
            new("自动确认", $"订单 {order.Id} 发货超 30 天,自动确认收货", false),

        { Status: OrderStatus.Shipped } =>
            new("跟踪", $"订单 {order.Id} 物流跟踪中", false),

        // ========== 已完成订单 ==========
        { Status: OrderStatus.Completed, IsVipCustomer: true } =>
            new("回访", $"VIP 订单 {order.Id} 已完成,安排满意度回访", true),

        { Status: OrderStatus.Completed } =>
            new("评价", $"订单 {order.Id} 邀请用户评价", false),

        // ========== 已取消订单 ==========
        { Status: OrderStatus.Cancelled, PayTime: not null } =>
            new("退款", $"订单 {order.Id} 已取消,启动退款流程", true),

        { Status: OrderStatus.Cancelled } =>
            new("关闭", $"订单 {order.Id} 已取消,释放库存", false),

        // ========== 兜底 ==========
        _ => new("未知", $"订单 {order.Id} 状态异常,需人工排查", true)
    };

    // 辅助方法:纯函数,无副作用
    private static bool IsExpired(DateTime createTime) =>
        (DateTime.Now - createTime).Hours > 24;

    private static bool IsShippingOverdue(DateTime? payTime) =>
        payTime.HasValue && (DateTime.Now - payTime.Value).Hours > 48;
}

// 测试程序
class Program
{
    static void Main()
    {
        var processor = new OrderProcessor();

        // 构造测试订单
        var orders = new[]
        {
            new Order(1, OrderStatus.Pending, 15000m, DateTime.Now.AddHours(-1), null, false),
            new Order(2, OrderStatus.Pending, 500m, DateTime.Now.AddHours(-25), null, false),
            new Order(3, OrderStatus.Pending, 200m, DateTime.Now.AddHours(-2), null, true),
            new Order(4, OrderStatus.Paid, 8000m, DateTime.Now.AddDays(-3), DateTime.Now.AddDays(-2), false),
            new Order(5, OrderStatus.Paid, 300m, DateTime.Now.AddDays(-1), DateTime.Now.AddDays(-1), false),
            new Order(6, OrderStatus.Shipped, 600m, DateTime.Now.AddDays(-35), DateTime.Now.AddDays(-33), false),
            new Order(7, OrderStatus.Completed, 1200m, DateTime.Now.AddDays(-10), DateTime.Now.AddDays(-11), true),
            new Order(8, OrderStatus.Cancelled, 900m, DateTime.Now.AddDays(-5), DateTime.Now.AddDays(-4), false),
            new Order(9, OrderStatus.Cancelled, 100m, DateTime.Now.AddDays(-1), null, false)
        };

        Console.WriteLine("========== 订单处理结果 ==========\n");

        foreach (var order in orders)
        {
            var result = processor.ProcessOrder(order);
            Console.WriteLine($"订单 {order.Id,2} | 状态:{order.Status,-10} | 金额:{order.Amount,8:C} | VIP:{order.IsVipCustomer,-5}");
            Console.WriteLine($"         | 动作:{result.Action,-8} | 通知:{result.NeedNotify,-5} | {result.Message}");
            Console.WriteLine();
        }
    }
}

输出示例 ​

========== 订单处理结果 ==========

订单  1 | 状态:Pending    | 金额:¥15,000.00 | VIP:False
         | 动作:审核      | 通知:True  | 订单 1 金额过大(¥15,000.00),需人工审核

订单  2 | 状态:Pending    | 金额:  ¥500.00 | VIP:False
         | 动作:取消      | 通知:False | 订单 2 已超时(创建时间:10-06 07:00),自动取消

订单  3 | 状态:Pending    | 金额:  ¥200.00 | VIP:True
         | 动作:提醒      | 通知:True  | VIP 订单 3 待支付,发送专属提醒

订单  4 | 状态:Paid       | 金额: ¥8,000.00 | VIP:False
         | 动作:优先发货   | 通知:True  | 大额订单 4,安排优先发货

订单  5 | 状态:Paid       | 金额:  ¥300.00 | VIP:False
         | 动作:发货      | 通知:False | 订单 5 正常发货流程

订单  6 | 状态:Shipped    | 金额:  ¥600.00 | VIP:False
         | 动作:自动确认   | 通知:False | 订单 6 发货超 30 天,自动确认收货

订单  7 | 状态:Completed  | 金额: ¥1,200.00 | VIP:True
         | 动作:回访      | 通知:True  | VIP 订单 7 已完成,安排满意度回访

订单  8 | 状态:Cancelled  | 金额:  ¥900.00 | VIP:False
         | 动作:退款      | 通知:True  | 订单 8 已取消,启动退款流程

订单  9 | 状态:Cancelled  | 金额:  ¥100.00 | VIP:False
         | 动作:关闭      | 通知:False | 订单 9 已取消,释放库存

七、核心知识点总结 ​

7.1 版本演进速查表 ​

版本特性示例
C# 1.0传统 switch 语句switch(x) { case 1: ... break; }
C# 7.0类型模式 + when 守卫case int i when i > 0:
C# 8.0switch 表达式x switch { 1 => "一", _ => "其他" }
C# 9.0关系/逻辑/属性/位置模式{ Age: >= 18 }, (0, 0)
C# 10.0扩展 or 模式组合更复杂的嵌套 or
C# 11.0列表模式[1, ..], [.., 3]

7.2 模式匹配速查表 ​

模式类型语法示例说明
常量模式42, "hello", Color.Red匹配具体值
类型模式int i, string s匹配类型并捕获变量
关系模式> 0, < 100, >= 18范围比较
逻辑模式and, or, not组合多个模式
属性模式{ Age: >= 18 }匹配对象属性
位置模式(0, 0), (var x, var y)解构匹配
弃元模式_匹配任意值(兜底)
var 模式var x匹配任意值并捕获

7.3 最佳实践指南 ​

  1. 优先使用 switch 表达式:代码更简洁,编译器强制穷尽匹配
  2. 枚举是 switch 的最佳搭档:类型安全 + 智能提示 + 重构支持
  3. 用 _ 兜底所有未预见情况:避免漏处理新增枚举值
  4. when 守卫保持纯判断:不修改状态,不产生副作用
  5. 复杂业务用属性模式:比多层 if-else 嵌套更易读
  6. 字符串匹配注意 null 和大小写:显式处理 null,统一 ToLower/ToUpper
  7. 浮点数避免精确匹配:用范围或阈值替代
  8. 性能敏感场景实测:不要凭直觉,用 BenchmarkDotNet 验证

7.4 传统 vs 现代:何时用哪个 ​

场景推荐方案
需要返回值的简单映射switch 表达式
分支内需要多行复杂逻辑传统 switch 语句
需要 fall-through 共享代码传统 switch(多个 case 标签)
模式匹配 + 穷尽检查switch 表达式
兼容旧版 C#(< 8.0)传统 switch 语句

结语 ​

switch 语句的演进史,就是 C# 语言「让代码更表达意图」的缩影。从最初简单的数值跳转,到如今支持模式匹配的函数式风格,switch 已经从一个「控制流工具」进化为「数据解构与业务规则表达」的核心武器。

掌握 switch 的关键心法:

  • 语法上:表达式优于语句,模式优于常量
  • 设计上:穷尽匹配是底线,_ 兜底是保险
  • 实战上:属性模式处理复杂对象,位置模式处理解构,when 守卫处理动态条件

当你下次面对一堆 else if 链时,不妨停下来想想:这段逻辑是否可以用 switch 表达式重写?往往你会发现,代码不仅更短,而且意图更清晰——这才是现代 C# 的优雅之道。