C# 模式匹配:从 is 到 switch 表达式的演进之路
【摘要】 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 语句相当,甚至在某些情况下更优:
- JIT 优化:编译器会对 switch 表达式进行优化,生成跳转表
- 可读性提升:更清晰的代码结构有助于 JIT 进行更好的优化
- 减少分支:表达式 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)