C#模式匹配详解
一、模式匹配核心概念
1.什么是模式匹配?
模式匹配是一种检查数据结构是否满足特定条件并提取信息的机制,取代传统的 if-else
或 switch
逻辑,使代码更简洁、安全。
2.核心优势
- 简洁性:减少类型检查和转换的冗余代码
- 安全性:编译时检查模式的有效性(如属性是否存在)
- 表达力:支持嵌套、递归和逻辑组合模式
二、核心模式类型与语法
1.类型模式(Type Pattern)
- 用途:检查对象是否为指定类型,并提取变量
- 语法:变量 is 类型 标识符
object obj = "HaHaHa"
if (obj is string s)
{
Console.WriteLine("s.length"); //直接使用s,无需显式转换
}
//注意:匹配失败时s不会被赋值
2.常量模式(Constant Pattern)
- 用途:匹配常量值(如整数、字符串、null)
- 语法:变量 is [常量值]
int number = 1;
if (number is 1)
{
Console.WriteLine("值为1");
}
string str = null;
if(text is null)
{
Console.WriteLine("空值");
}
3.变量模式(Var Pattern)
- 用途:将值捕获到临时变量,通常结合 when 使用
object obj = 3.14;
if (obj is var temp && temp is double)
{
Console.WriteLine($"Double value: {temp}");
}
4.属性模式(Property Pattern)
- 用途:匹配对象的属性值
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person p = new Person { Name = "VTheshow", Age = 100 };
if (p is { Name: "VTheshow", Age: >= 18 })
{
Console.WriteLine("VTheshow年龄大于18");
}
5.元组模式(Tuple Pattern)
- 用途:同时匹配多个值的元组
var point = (x: 0, y: 1);
if (point is (0, 1))
{
Console.WriteLine("坐标匹配");
}
// 结合类型和属性
var result = point switch
{
(0, 0) => "原点",
(var x, var y) when x == y => "对角线",
_ => "其他"
};
6.位置模式(Positional Pattern)
- 用途:匹配解构后的对象(需实现 Deconstruct 方法)
public record Point(int X, int Y); // 自动生成 Deconstruct
Point pt = new Point(2, 3);
if (pt is (2, 3))
{
Console.WriteLine("匹配坐标 (2,3)");
}
7.递归模式(Recursive Pattern)
- 用途:嵌套组合多种模式
if (obj is Person { Name: "HaHa", Age: int age } && age > 20)
{
Console.WriteLine("HaHa 年龄超过 20");
}
8.逻辑模式(Logical Pattern)
- C#9.0+支持:使用and、or、not组合条件
int num = 15;
if (num is > 10 and < 20)
{
Console.WriteLine("介于 10 和 20 之间");
}
string text = "effective value"
if (text is not null and not "unknown")
{
Console.WriteLine("有效值");
}
9.列表模式(List Pattern)
- C#11+支持:匹配数组或列表的元素
int[] numbers = { 1, 2, 3 };
if (numbers is [1, 2, 3])
{
Console.WriteLine("完全匹配");
}
if (numbers is [1, .. var rest])
{
Console.WriteLine($"剩余元素数量: {rest.Length}"); // 输出 2
}
// 匹配任意长度的列表
if (numbers is [.., 3])
{
Console.WriteLine("以 3 结尾");
}
三、switch表达式
- 用途:简化switch语句,直接返回值
string Describe(object obj) => obj switch
{
int i when i > 0 => "正整数",
double d => $"双精度数: {d}",
string s => $"字符串: {s}",
null => "空值",
_ => "未知类型"
};
Console.WriteLine(Describe(5)); // 输出 "正整数"
注意事项
- 模式顺序:switch 分支按顺序匹配,优先放置具体模式
- 穷尽性检查:使用 _ 默认分支处理未覆盖的情况
- 性能:模式匹配通常编译为高效代码,无需担心性能损失
四、实际应用场景
1.替代类型检查与转换
class Circle
{
public float Radius { get; set; }
}
// 传统写法
if (shape is Circle)
{
Circle c = (Circle)shape;
Console.WriteLine(c.Radius);
}
// 模式匹配写法
if (shape is Circle c)
{
Console.WriteLine(c.Radius);
}
2.处理复杂条件
public class IncomeData
{
public decimal Income { get; set; }
public bool IsCitizen { get; set; }
}
string GetTaxCategory(IncomeData data) => data switch
{
{ Income: < 10000 } => "低收入",
{ Income: >= 10000 and < 50000, IsCitizen: true } => "中等收入公民",
{ Income: >= 50000 } => "高收入",
_ => "其他"
};
关键点总结
- 属性模式的依赖:属性模式要求目标类型(如
IncomeData
)必须包含对应的属性(如Income
和IsCitizen
),且属性可访问(通常是public
)
- 模式匹配的优势:这种写法比传统的
if-else
更简洁,尤其是当条件涉及多个属性或嵌套对象时 - 编译时安全:如果拼写错误(如写成
Incom
而不是Income
),编译器会直接报错,避免运行时错误
3.解构嵌套对象
if (student is { Address: { City: "Beijing", ZipCode: "100000" } })
{
Console.WriteLine("北京学生");
}
五、版本支持
C#版本 | 支持特性 |
7.0 | 基本类型模式、常量模式 |
8.0 | switch 表达式、递归模式、属性模式 |
9.0 | 逻辑模式 (and /or /not ) |
10.0 | 扩展属性模式(支持嵌套属性) |
11.0 | 列表模式、模式匹配 Span<char> |