新式 switch 是表达式,必须有返回值、覆盖所有情况且支持模式嵌套;老式 switch 是语句,依赖 break 防穿透,易出错。

switch 表达式怎么写,和老式 switch 语句有什么关键区别
新式 switch 是表达式,必须有返回值,不能漏掉 => 和表达式体;老式 switch 是语句,靠 break 防止穿透,容易漏写导致逻辑错误。
- 必须覆盖所有可能输入(或加
_ => throw new ArgumentException()捕获遗漏);编译器会检查是否穷尽,比如对enum切换时,少一个 case 就报错 - 模式可嵌套:比如
case Point { X: > 0, Y: $"Q4: {p}",直接解构 + 条件判断 - 不能用
goto case或goto default—— 它不是语句,不支持跳转 - 示例:
string Describe(object o) => o switch { int i when i < 0 => "negative int", int i => $"positive or zero: {i}", string s when s.Length > 10 => "long string", string s => $"short string: '{s}'", null => "nothing", _ => "something else" };
is 模式匹配中 var、类型、属性模式怎么选
is 后面跟的不是“类型判断开关”,而是“一次完成类型检查 + 变量绑定 + 结构解构”的组合操作;选哪种模式取决于你后续要不要用值、要不要验字段。
-
obj is string s:最常用,类型检查成功后把obj转成string绑定到s,s在作用域内可用 -
obj is Person { Name: "Alice", Age: >= 18 }:属性模式,自动做非空检查 + 字段匹配,Name和Age不需要再判null或拆箱 -
obj is var x:永远为 true,只做变量绑定(类似var x = obj),但可用于空检查场景:if (obj is var v && v != null) - 注意:
is string不绑定变量,等价于obj is string == true,但丢了值;要取值必须写is string s
模式匹配在泛型方法或 as 操作符里为什么失效
泛型类型参数(如 T)在运行时擦除,编译器无法生成具体的类型检查逻辑,所以 obj is T t 在 .NET 5+ 之前是编译错误;as 也不支持模式(obj as string s 是非法语法)。
- 替代方案:用
obj is T t && t != null(.NET 6+ 支持泛型is,但需确保T是引用类型或有约束) - 更安全的泛型写法:
if (obj is T t && t is not null) { /* use t */ },避免值类型误判 -
as只能转型,不能绑定变量;想同时转型+绑定,必须用is模式 - 常见报错:
CS8121: An expression of type 'object' cannot be handled by a pattern of type 'T'—— 这说明你正在泛型上下文中用了未约束的类型模式
switch 表达式嵌套或和 LINQ 混用时性能要注意什么
模式匹配本身开销很小,但嵌套过深或在热路径里频繁构造匿名对象/调用方法,会放大 GC 压力;LINQ 的延迟执行 + 模式匹配组合容易写出“看着简洁、跑着慢”的代码。
- 避免在
case分支里写复杂 LINQ 链(如.Select(...).Where(...).First()),尤其当输入集合大时;先用is提前过滤,再进switch - 不要在
switch中反复调用可能返回不同类型的GetValue()方法再匹配——改用一次获取 + 多重模式分支 - 值类型匹配(如
int,DateTime)无装箱,但object输入进switch会触发模式内部的隐式转换,注意is int i对long值永远 false - 调试时留意反编译结果:简单模式会被编译为
isinst+castclass,而带when的会生成额外 lambda,影响内联
实际用的时候,最容易被忽略的是 switch 表达式的穷尽性检查和泛型上下文中的类型擦除限制——这两处不提前踩坑,后面 debug 会卡很久。


















