<p>C# 8.0+ 的 switch 表达式支持模式匹配,可解构对象、判断类型、检查属性;传统 switch 语句仅支持常量表达式,不支持模式。</p>

switch 语句在 C# 8.0+ 中已不是“只能比值”的老古董——它支持模式匹配,能直接解构对象、判断类型、检查属性,但前提是必须用 switch 表达式(=>)或带 when 的 case,且目标类型需支持模式(如 class、record、nullable 等)。
什么时候该用 switch 表达式而不是传统 switch 语句
当你需要返回一个值、避免 break 遗漏、或处理嵌套条件时,优先选 switch 表达式。它强制穷尽性检查(编译器报错提醒你漏了 case),也天然支持模式。传统 switch 语句(带 case 和 break)不支持模式匹配,只接受常量表达式(如 case 1:、case "abc":)。
- 用
switch表达式:var result = obj switch { Person p when p.Age > 18 => "adult", ... }; - 用传统
switch语句:仅限int、string、enum等可隐式转为常量的类型,且不能写when或类型模式 - 注意:C# 8 起
switch表达式要求所有可能路径都有对应分支,否则编译失败;若变量是object或基类,编译器无法静态推断穷尽性,需加_ => throw new ArgumentException();收尾
case 中的类型模式(Person p)怎么写才不报错
类型模式语法是 类型名 变量名,但它只在 switch 表达式或带 when 的 case 中合法。直接写 case Person p: 在传统语句里会编译失败。
- ✅ 正确(表达式):
obj switch { Person p => p.Name, Student s => s.StudentId, _ => "unknown" } - ✅ 正确(带 when):
case Person p when p.Age >= 65:(注意这是传统语句中的写法,需配合break) - ❌ 错误:
case Person p:(传统语句中不允许单独类型模式) - ⚠️ 注意:类型模式会做运行时类型检查 + 变量绑定,如果
obj是null,模式不匹配(不会抛异常),所以下面的p在分支内非 null —— 这是安全的,但别指望它自动处理 null 分支,得显式写null => ...或用_
如何用 property pattern 匹配对象内部字段(比如只看 Age 和 Name)
property pattern 允许你按对象的属性值做匹配,语法是 TypeName { Prop1: value1, Prop2: value2 },支持嵌套和通配符。
- 示例:
person switch { Person { Age: >= 18, Name: not null } => "valid adult", Person { Age: < 18 } => "minor", _ => "invalid" } -
not null是常量模式,>= 18是关系模式,它们必须和 property pattern 组合使用,不能单独出现在case常量位置 - 嵌套也行:
Order { Customer: { IsPremium: true } } => "priority" - 性能提示:每次匹配都会访问属性(可能触发 getter),如果属性有副作用或开销大,慎用;简单 readonly 字段没问题
常见编译错误和绕过方法
最常遇到的是 CS8509: The switch expression does not handle all possible inputs(穷尽性检查失败)和 CS8121: An expression of type 'X' cannot be handled by a pattern of type 'Y'(类型不兼容)。
-
CS8509:给switch表达式末尾加_ => throw new UnreachableException();或合理默认分支,尤其当输入是object或基类时 -
CS8121:说明你写的模式类型和输入类型无继承/实现关系,比如对int写case string s:——int永远不是string,编译器直接拒绝 - 另一个坑:
switch表达式要求所有分支返回相同类型,void不行;如果某分支想执行动作不返回值,改用传统switch语句 +when - 调试建议:把表达式拆成独立变量,比如先写
var match = obj is Person p;看是否为 true,再逐步加 property 条件
模式匹配的灵活性来自编译器生成的类型检查与属性访问代码,不是语法糖;真正难的不是写对语法,而是想清楚哪些分支必须覆盖、哪些 null 或边界情况容易被 property pattern 静默跳过——尤其是当对象来自外部 API 或反序列化时。


















