C# 模式匹配:从 is 到 switch 表达式的演进之路

举报
yd_297983512 发表于 2026/10/10 00:42:26 2026/10/10
【摘要】 C# 模式匹配:从 is 到 switch 表达式的演进之路

C# 模式匹配:从 is 到 switch 表达式的演进之路

作者:CodeArts
日期:2026-04-02
标签:C# .NET 模式匹配


引言

如果你还在用 if (obj is string) 来判断类型,那 C# 9.0 之后的模式匹配新特性可能会让你大开眼界。从 C# 7.0 引入基础模式匹配,到 C# 8.0 的 switch 表达式,再到 C# 9.0 的 relational 模式,C# 的模式匹配能力已经发生了质的飞跃。

今天,我们就来系统梳理一下 C# 模式匹配的演进历程。


C# 7.0:模式匹配的起点

C# 7.0 首次引入了模式匹配的概念,主要通过 is 表达式和 switch 语句来体现。

常量模式

object obj = 42;

if (obj is 42)
{
    Console.WriteLine("答案是 42!");
}

类型模式

public void PrintShape(object shape)
{
    if (shape is Circle c)
    {
        Console.WriteLine($"圆形,半径:{c.Radius}");
    }
    else if (shape is Rectangle r)
    {
        Console.WriteLine($"矩形,宽高:{r.Width} x {r.Height}");
    }
}

var 模式

if (shape is var s)
{
    Console.WriteLine(s?.GetType().Name);
}

C# 8.0:Switch 表达式

C# 8.0 带来了革命性的 switch 表达式,让代码更加简洁优雅。

传统 switch vs 表达式 switch

// 传统写法
public string GetDayName(int day)
{
    switch (day)
    {
        case 1: return "Monday";
        case 2: return "Tuesday";
        case 3: return "Wednesday";
        case 4: return "Thursday";
        case 5: return "Friday";
        case 6: return "Saturday";
        case 7: return "Sunday";
        default: throw new ArgumentException("Invalid day");
    }
}

// 表达式写法
public string GetDayName(int day) => day switch
{
    1 => "Monday",
    2 => "Tuesday",
    3 => "Wednesday",
    4 => "Thursday",
    5 => "Friday",
    6 => "Saturday",
    7 => "Sunday",
    _ => throw new ArgumentException("Invalid day")
};

属性模式

public decimal CalculateDiscount(Customer customer)
{
    return customer switch
    {
        { IsVip: true, Years: >= 5 } => 0.3m,
        { IsVip: true, Years: >= 1 } => 0.2m,
        { IsVip: true } => 0.1m,
        { Years: >= 10 } => 0.05m,
        _ => 0m
    };
}

元组模式

public string GetRockPaperScissors(string player1, string player2) => (player1, player2) switch
{
    ("Rock", "Scissors") => "Player 1 wins",
    ("Scissors", "Rock") => "Player 2 wins",
    ("Paper", "Rock") => "Player 1 wins",
    ("Rock", "Paper") => "Player 2 wins",
    ("Scissors", "Paper") => "Player 1 wins",
    ("Paper", "Scissors") => "Player 2 wins",
    _ => "Draw"
};

C# 9.0:关系模式与逻辑模式

C# 9.0 进一步扩展了模式匹配的能力,引入了关系运算符和逻辑运算符。

关系模式

public string GetTemperatureCategory(double temp) => temp switch
{
    < -10 => "极寒",
    < 0 => "寒冷",
    < 10 => "凉爽",
    < 20 => "温暖",
    < 30 => "炎热",
    _ => "酷热"
};

逻辑模式

public string GetWaterState(double temp) => temp switch
{
    < 0 => "固态",
    >= 0 and < 100 => "液态",
    >= 100 => "气态"
};

// 组合使用
public string GetGrade(int score) => score switch
{
    >= 90 and <= 100 => "A",
    >= 80 and < 90 => "B",
    >= 70 and < 80 => "C",
    >= 60 and < 70 => "D",
    < 60 => "F",
    _ => "无效分数"
};

not 模式

public bool IsValidEmail(string email) => email is not null and not "" and not " ";

// 更复杂的例子
public string GetAccessLevel(User user) => user switch
{
    { IsActive: false } => "无权限",
    { IsAdmin: true } => "管理员",
    { IsBanned: true } => "已封禁",
    not null => "普通用户",
    null => "未登录"
};

C# 10/11/12:持续进化

C# 10:扩展属性模式

// 传统写法
if (person is { Address: { City: "Shanghai" } })
{
    Console.WriteLine("上海居民");
}

// 扩展属性模式
if (person is { Address.City: "Shanghai" })
{
    Console.WriteLine("上海居民");
}

C# 11:列表模式

public string CheckList(int[] numbers) => numbers switch
{
    [1, 2, 3] => "精确匹配",
    [_, 2, _] => "中间是 2",
    [.., 99] => "以 99 结尾",
    [1, ..] => "以 1 开头",
    [] => "空列表",
    _ => "其他"
};

C# 12:Primary Constructor 与模式匹配

public record Product(string Name, decimal Price, int Stock);

public string GetProductStatus(Product p) => p switch
{
    { Price: > 1000, Stock: > 0 } => "高价有货",
    { Price: > 1000, Stock: 0 } => "高价缺货",
    { Price: <= 1000, Stock: > 10 } => "低价充足",
    { Price: <= 1000, Stock: <= 10 } => "低价紧张",
    _ => "未知"
};

实战案例:状态机实现

让我们用模式匹配来实现一个简单的订单状态机:

public enum OrderStatus
{
    Pending,
    Paid,
    Shipped,
    Delivered,
    Cancelled
}

public record Order(Guid Id, OrderStatus Status, decimal Amount);

public string GetOrderAction(Order order) => order switch
{
    { Status: OrderStatus.Pending } => "等待支付",
    { Status: OrderStatus.Paid, Amount: > 1000 } => "大额订单,需要审核发货",
    { Status: OrderStatus.Paid } => "准备发货",
    { Status: OrderStatus.Shipped } => "运输中",
    { Status: OrderStatus.Delivered } => "已完成",
    { Status: OrderStatus.Cancelled } => "已取消",
    _ => "未知状态"
};

// 状态转换验证
public bool CanTransition(OrderStatus from, OrderStatus to) => (from, to) switch
{
    (OrderStatus.Pending, OrderStatus.Paid) => true,
    (OrderStatus.Pending, OrderStatus.Cancelled) => true,
    (OrderStatus.Paid, OrderStatus.Shipped) => true,
    (OrderStatus.Shipped, OrderStatus.Delivered) => true,
    _ => false
};

性能考量

模式匹配在性能上与传统 if-else 或 switch 语句相当,甚至在某些情况下更优:

  1. JIT 优化:编译器会对 switch 表达式进行优化,生成跳转表
  2. 可读性提升:更清晰的代码结构有助于 JIT 进行更好的优化
  3. 减少分支:表达式 switch 是表达式而非语句,可以被内联优化

最佳实践

✅ 推荐

// 使用模式匹配简化复杂条件
public string GetDiscountLevel(Customer c) => c switch
{
    { IsVip: true, Years: >= 5 } => "钻石会员",
    { IsVip: true } => "黄金会员",
    { Orders.Count: >= 10 } => "银卡会员",
    _ => "普通会员"
};

// 使用列表模式处理集合
public bool IsValidMatrix(int[][] matrix) => matrix is
{
    Length: > 0,
    [_, ..] => true
};

❌ 避免

// 过度嵌套,降低可读性
if (person is { Address: { City: { Length: > 0 } } })
{
    // 太复杂了!
}

// 应该拆分成多个条件
if (person?.Address?.City is { Length: > 0 } city)
{
    // 更清晰
}

总结

C# 模式匹配的演进之路,体现了语言设计者对表达力和简洁性的不懈追求:

版本 核心特性
C# 7.0 is 表达式、常量模式、类型模式、var 模式
C# 8.0 switch 表达式、属性模式、元组模式
C# 9.0 关系模式、逻辑模式(and/or/not)
C# 10 扩展属性模式
C# 11 列表模式
C# 12 Primary Constructor 深度集成

模式匹配让 C# 从一门"面向对象语言"进化为一门兼具函数式编程特性的现代语言。掌握这些特性,能让你的代码更加简洁、安全、易读。


欢迎在评论区分享你对模式匹配的看法!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。