简介
模式匹配是 C# 7.0 开始引入的革命性特性,它提供了更简洁、更强大的方式来检查和提取数据中的信息。随着每个版本的更新,模式匹配功能不断强化,成为现代 C# 开发的核心特性。
模式匹配允许将输入表达式与各种特征进行匹配,支持多种模式类型。它主要用于:
is表达式:检查并可能声明变量。switch语句:传统分支逻辑。switch表达式:更简洁的表达式形式(C# 8.0引入)。
模式匹配演进历程
| 版本 | 新增特性 |
|---|---|
| C# 7.0 | 基本模式匹配:is 表达式、switch 语句增强 |
| C# 8.0 | 递归模式、属性模式、位置模式、switch 表达式 |
| C# 9.0 | 类型模式简化、逻辑模式(and/or/not)、关系模式 |
| C# 10.0 | 扩展属性模式 |
| C# 11.0 | 列表模式、切片模式 |
基础模式类型
声明模式
1// 检查类型并声明新变量 2if (obj is string str) 3{ 4 Console.WriteLine($"字符串长度: {str.Length}"); 5} 6 7// 传统方式对比 8if (obj is string) 9{ 10 string str = (string)obj; 11 Console.WriteLine($"字符串长度: {str.Length}"); 12} 13
类型模式
1// 只检查类型,不声明变量 2if (obj is string) 3{ 4 Console.WriteLine("这是一个字符串"); 5} 6 7// 在 switch 表达式中使用 8var result = obj switch 9{ 10 string => "它是字符串", 11 int => "它是整数", 12 _ => "其他类型" 13}; 14
常量模式
1// 检查特定值 2if (value is 5) { /* 值等于5 */ } 3if (value is null) { /* 值为null */ } 4if (value is "hello") { /* 字符串比较 */ } 5 6// 在 switch 中 7string message = value switch 8{ 9 0 => "零", 10 1 => "一", 11 null => "空值", 12 _ => "其他值" 13}; 14
高级模式匹配
属性模式
1// 检查对象属性 2if (person is { Name: "John", Age: > 18 }) 3{ 4 Console.WriteLine("John 已成年"); 5} 6 7// 嵌套属性模式 8if (order is { Customer: { Address: { City: "Beijing" } } }) 9{ 10 Console.WriteLine("北京客户的订单"); 11} 12 13// C# 10 扩展属性模式 14if (order is { Customer.Address.City: "Beijing" }) 15{ 16 Console.WriteLine("北京客户的订单(简化写法)"); 17} 18
位置模式(元组模式)
1// 元组解构和匹配 2var point = (x: 5, y: 10); 3var quadrant = point switch 4{ 5 (0, 0) => "原点", 6 (var x, var y) when x > 0 && y > 0 => "第一象限", 7 (var x, var y) when x < 0 && y > 0 => "第二象限", 8 (var x, var y) when x < 0 && y < 0 => "第三象限", 9 (var x, var y) when x > 0 && y < 0 => "第四象限", 10 _ => "在坐标轴上" 11}; 12
逻辑模式(C# 9.0+)
1// 使用逻辑运算符组合模式 2bool IsValid(object obj) => obj is not null and (string or int); 3 4// 复杂逻辑组合 5var category = value switch 6{ 7 > 0 and < 10 => "小的正数", 8 < 0 or > 100 => "超出范围", 9 not null => "非空值", 10 _ => "其他" 11}; 12
关系模式(C# 9.0+)
1// 使用关系运算符 2string GetSize(int value) => value switch 3{ 4 < 0 => "负数", 5 >= 0 and < 10 => "小", 6 >= 10 and < 100 => "中", 7 >= 100 => "大" 8}; 9 10// 与类型模式结合 11string Describe(object obj) => obj switch 12{ 13 int i when i < 0 => "负整数", 14 int i when i > 0 => "正整数", 15 int => "零", 16 _ => "其他" 17}; 18
列表模式(C# 11.0+)
1// 匹配数组或列表的特定模式 2int[] numbers = { 1, 2, 3, 4 }; 3 4var result = numbers switch 5{ 6 [1, 2, 3, 4] => "精确匹配", 7 [1, 2, ..] => "以1,2开头", 8 [.., 3, 4] => "以3,4结尾", 9 [1, .. var middle, 4] => $"以1开头4结尾,中间有{middle.Length}个元素", 10 [] => "空数组", 11 _ => "其他模式" 12}; 13 14// 切片模式 15if (numbers is [var first, .. var rest]) 16{ 17 Console.WriteLine($"第一个元素: {first}, 剩余元素: {rest.Length}"); 18} 19
字符串模式
1string text = "Hello, World"; 2 3if (text is ['H','e','l','l','o', ..]) 4{ 5 Console.WriteLine("以Hello开头"); 6} 7 8// 与Span<char>模式匹配结合 9ReadOnlySpan<char> span = text.AsSpan(); 10if (span is ['H','e','l','l','o', ..]) 11{ 12 Console.WriteLine("匹配Span"); 13} 14
自定义模式匹配
1// 通过 Deconstruct 方法支持位置模式 2public class Point 3{ 4 public int X { get; } 5 public int Y { get; } 6 7 public void Deconstruct(out int x, out int y) 8 { 9 x = X; 10 y = Y; 11 } 12} 13 14// 现在可以对 Point 使用位置模式 15var quadrant = point switch 16{ 17 (0, 0) => "原点", 18 (var x, var y) when x > 0 && y > 0 => "第一象限", 19 // ... 20};w 21
表达式树中的模式匹配
1Expression<Func<object, bool>> expr = o => o switch 2{ 3 int i when i > 0 => true, 4 string s when s.Length > 5 => true, 5 _ => false 6}; 7 8// 解析表达式树 9if (expr.Body is SwitchExpression switchExpr) 10{ 11 foreach (SwitchCase @case in switchExpr.Cases) 12 { 13 // 处理每个case 14 } 15} 16
实际应用场景
数据验证和处理
1public ValidationResult Validate(Order order) 2{ 3 return order switch 4 { 5 null => ValidationResult.Failure("订单不能为空"), 6 { TotalAmount: <= 0 } => ValidationResult.Failure("金额必须大于0"), 7 { Customer: null } => ValidationResult.Failure("客户信息缺失"), 8 { Items: [] } => ValidationResult.Failure("订单项不能为空"), 9 { Status: OrderStatus.Cancelled } => ValidationResult.Failure("订单已取消"), 10 _ => ValidationResult.Success() 11 }; 12} 13
API 响应处理
1public string HandleResponse(ApiResponse response) 2{ 3 return response switch 4 { 5 { StatusCode: 200, Data: not null } => "成功", 6 { StatusCode: 404 } => "资源未找到", 7 { StatusCode: >= 400 and < 500 } => "客户端错误", 8 { StatusCode: >= 500 } => "服务器错误", 9 { Error: not null } => $"错误: {response.Error.Message}", 10 _ => "未知响应" 11 }; 12} 13
《告别 if-else:C#.NET 模式匹配让代码更优雅的正确方式》 是转载文章,点击查看原文。
