switch表达式必须返回值且类型统一,禁止fall-through和goto case,支持高级模式匹配,而传统switch语句无此约束。

传统 switch 语句是语句,switch 表达式是表达式——这个根本差异决定了几乎所有行为区别。别想着“把 case 换成 => 就完事”,结构变了,约束和逻辑就全不一样。
必须返回值,否则编译直接报错
传统 switch 可以只执行动作(比如 Console.WriteLine、修改字段),不强制返回;switch 表达式则必须为每个分支提供一个计算结果,整个表达式本身就是一个值。
- 写
obj switch { string s => Console.WriteLine(s) }?不行,Console.WriteLine返回void,编译器报CS8506: No best type was found for the switch expression - 想打日志又返回值?得包装:
string s => { Console.WriteLine(s); return $"logged: {s}"; },但这就失去表达式的简洁性了 - 函数签名若声明返回
string,所有分支的右侧表达式类型必须统一可隐式转为string,不能有的返回int、有的返回null(除非目标类型是string?)
没有 break,也没有 fall-through,更没有 goto case
传统 switch 靠 break 防穿透,漏写就会意外执行下一个 case;switch 表达式里压根没这概念——每个分支完全独立,顺序无关,也禁止跳转。
-
goto case 2;或goto default;在表达式中非法,语法错误 - 多个模式匹配同一输入?编译器直接报
CS8510: The pattern is already handled by a previous arm(比如写了两次int i) - 枚举值没全覆盖?比如
DayOfWeek少了Saturday,编译警告CS8509,开#nullable enable下可能升级为错误
模式匹配能力是质变,不是语法糖
传统 switch 只能匹配常量(1、"abc"、MyEnum.Value);switch 表达式原生支持类型模式、守卫条件、组合模式、属性解构——这些不是“锦上添花”,而是解决真实问题的刚需。
-
null是合法模式,不用再写if (obj == null)预检 -
string s when s.Length > 0一次性完成「判类型 + 绑定变量 + 验长度」,不用is string s && s.Length > 0两步 Point { X: > 0, Y: 直接解构对象属性,比 <code>if (p is Point && p.X > 0 && p.Y 更安全(自动非空检查)-
DayOfWeek.Saturday or DayOfWeek.Sunday共享处理逻辑,比两个重复case干净得多
兜底必须显式写 _ =>,不能省略也不能用 default
_ 不是“随便什么”,它是编译器做穷尽检查的锚点。漏掉它,或者误写成 default =>(那是语句语法),编译器就不知道你是否真想覆盖全部路径。
- 对
int这种无法穷举的类型,_ => "other"是必需的;对enum,即使你列出了所有成员,仍建议加_ => throw new UnreachableException(),防止未来新增枚举值后编译器不报警 -
default在表达式中无效,写了会报CS8642: Default label is not valid in a switch expression - 如果真想让未匹配情况抛异常,别用空
_ => throw ...,要确保异常类型与其它分支返回类型兼容(比如都返回string,就用_ => throw new ArgumentException()然后函数返回string—— 这行不通;正确做法是函数返回string,所有分支都返回string,异常只能放外面或改用??后续处理)
最易被忽略的是:模式匹配的嵌套深度和类型约束会影响编译时检查力度。比如在泛型方法里对 T 做 is T t,若 T 无约束,.NET 6+ 之前直接编译失败;而 switch 表达式里写 obj switch { T t => ... } 同样不被允许——这种限制不是语法缺陷,是类型系统在帮你提前拦截运行时错误。











