前置知识: C#

模式匹配

2 minIntermediate2026/6/14

C#模式匹配与switch表达式

概述

C# 的模式匹配从 C# 7 开始引入,经过多个版本的增强,已成为表达条件逻辑的强大工具。模式匹配支持型检查、属性解构、列表匹配和逻辑组合,配合 switch 表达式可以写出简洁而安全的分支代码。

基础概念

模式

模式语法版本说明
型模式is TypeC# 7检查型并提取值
属性模式is { Prop: val }C# 8检查属性值
位置模式is (a, b)C# 8基于解构匹配
列表模式is [1, 2, .., 5]C# 11匹配数组/列表元素
逻辑模式and, or, notC# 9组合模式
关系模式is > 0C# 9比较值

快速上手

型模式

// is 类型检查 + 智能转换
if (obj is string s) {
    Console.WriteLine(s.Length); // s 已自动转换为 string
}

// switch 中的类型模式
string Describe(object obj) => obj switch {
    int i => $"整数: {i}",
    double d => $"浮点数: {d:F2}",
    string s => $"字符串: {s}",
    null => "null",
    _ => "未知类型" // _ 是弃元模式,匹配任何值
};

属性模式

// 检查对象属性
if (person is { Age: >= 18, City: "北京" }) {
    Console.WriteLine("北京成年用户");
}

// 嵌套属性模式
if (order is { Customer.VipLevel: >= 3, TotalAmount: > 1000 }) {
    ApplyDiscount();
}

// switch 表达式中的属性模式
string Categorize(Person p) => p switch {
    { Age: < 13 } => "儿童",
    { Age: >= 13 and < 20 } => "青少年",
    { Age: >= 20 and < 60 } => "成年人",
    { Age: >= 60 } => "老年人",
};

switch 表达式

// switch 表达式(C# 8+)
string label = statusCode switch {
    200 => "OK",
    404 => "Not Found",
    >= 500 => "Server Error",
    _ => "Unknown"
};

// 元组模式
string GetDirection(int x, int y) => (x, y) switch {
    (0, 0) => "原点",
    (> 0, 0) => "正X轴",
    (0, > 0) => "正Y轴",
    (> 0, > 0) => "第一象限",
    (< 0, > 0) => "第二象限",
    _ => "其他"
};

详细用法

位置模式与解构

// 记录类型自动支持位置模式
public record Point(double X, double Y);
public record Circle(Point Center, double Radius);

string DescribeShape(Shape shape) => shape switch {
    Circle({ X: 0, Y: 0 }, var r) => $"以原点为圆心,半径 {r}",
    Circle(var center, var r) => $"圆心 ({center.X}, {center.Y}),半径 {r}",
    Rectangle(var w, var h) when w == h => $"正方形 {w}x{h}",
    Rectangle(var w, var h) => $"矩形 {w}x{h}",
};

// 自定义解构
public class User {
    public string Name { get; set; }
    public int Age { get; set; }

    public void Deconstruct(out string name, out int age) {
        name = Name;
        age = Age;
    }
}

// 使用位置模式
if (user is ("张三", var age)) {
    Console.WriteLine($"张三的年龄: {age}");
}

列表模式(C# 11)

// 匹配数组/列表
int[] arr = { 1, 2, 3, 4, 5 };

if (arr is [1, 2, .., 5]) {
    Console.WriteLine("以1,2开头,以5结尾");
}

if (arr is [var first, .., var last]) {
    Console.WriteLine($"首: {first}, 尾: {last}");
}

if (arr is [_, _, var third, ..]) {
    Console.WriteLine($"第三个元素: {third}");
}

// switch 中的列表模式
string Classify(int[] values) => values switch {
    [] => "空数组",
    [var single] => $"单元素: {single}",
    [var a, var b] => $"两个元素: {a}, {b}",
    [var first, .. var middle, var last] => $"首: {first}, 中: {middle.Length}个, 尾: {last}",
};

逻辑模式组合

// and, or, not 组合模式
bool IsValid(object obj) => obj is not null and (int or double or decimal);

string Classify(int n) => n switch {
    < 0 => "负数",
    0 => "零",
    > 0 and < 10 => "个位正数",
    >= 10 and < 100 => "两位正数",
    >= 100 => "三位及以上正数",
};

// not 模式
if (value is not null and not "") {
    Process(value);
}

常见场景

异常处理

// 使用模式匹配处理不同异常
catch (Exception ex) when (ex is HttpRequestException { StatusCode: System.Net.HttpStatusCode.NotFound }) {
    return "资源未找到";
}
catch (Exception ex) when (ex is HttpRequestException { StatusCode: var code } && (int)code >= 500) {
    return "服务器错误";
}
catch (Exception ex) when (ex is TimeoutException or OperationCanceledException) {
    return "请求超时";
}

领域事件处理

// 使用模式匹配处理领域事件
string HandleEvent(OrderEvent evt) => evt switch {
    OrderCreated { OrderId: var id, Amount: > 10000 } => $"大额订单创建: {id}",
    OrderCreated { OrderId: var id } => $"订单创建: {id}",
    OrderPaid { PaymentMethod: "credit_card" } => "信用卡支付完成",
    OrderPaid { PaymentMethod: var method } => $"{method} 支付完成",
    OrderShipped { TrackingNumber: var tracking } => $"已发货: {tracking}",
    OrderCancelled { Reason: var reason } => $"已取消: {reason}",
};

注意事项

  • 模式匹配的顺序很重要,更具体的模式应放在前面
  • 弃元模式 _ 必须放在最后,否则会遮盖后续模式
  • 属性模式中 null 检查是隐式的:{ Prop: value } 不会对 null 对象抛异常
  • 列表模式在 C# 11 中引入,需要确保项目使用 C# 11+
  • when 子句可以添加额外条件,但会降低模式匹配的穷举检查能力
  • 模式匹配在编译时会被优化,不会产生额外运行时开销

进阶用法

自定义模式(C# 13+)

// 使用静态方法实现自定义模式
public static class IntPatterns {
    // 自定义 Even 模式
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool Even(int value) => value % 2 == 0;
}

// 使用
if (number is > 0 and IntPatterns.Even) {
    Console.WriteLine("正偶数");
}

递归模式匹配

// 递归处理表达式树
int Eval(Expr expr) => expr switch {
    Literal { Value: var v } => v,
    Add { Left: var l, Right: var r } => Eval(l) + Eval(r),
    Mul { Left: var l, Right: var r } => Eval(l) * Eval(r),
    Neg { Operand: var o } => -Eval(o),
};

abstract record Expr;
record Literal(int Value) : Expr;
record Add(Expr Left, Expr Right) : Expr;
record Mul(Expr Left, Expr Right) : Expr;
record Neg(Expr Operand) : Expr;