switch表达式是编译期强制校验的模式匹配构造,cs8509因漏分支或缺兜底、cs8506因返回类型不一致而报错;需显式处理null、统一返回类型、用or合并枚举值、property pattern真实访问属性。

switch 表达式不是语法糖,它是编译期强制校验的模式匹配构造;写错立刻报 CS8509 或 CS8506,而不是运行时崩溃或逻辑遗漏。
为什么 switch 表达式编译失败:CS8509 和 CS8506
这两个错误不是“配置没开”或“版本太低”,而是类型契约被破坏的明确信号:
-
CS8509:输入类型可穷举(如DayOfWeek、enum、非空record),但你漏了某个分支;或对开放类型(如object、int)没写_ =>兜底 -
CS8506:各分支返回类型不一致——比如有的分支返回string,有的返回int,或null => throw而其他分支返回string -
null不会被_匹配,它是一个独立常量模式,必须显式写null => "xxx",否则obj为null时直接无匹配分支
object 类型安全解构 + 条件过滤,不用套娃 if (x is T t)
用 switch 表达式一次性完成类型检查、变量绑定、属性判断:
string result = obj switch
{
string s when s.Length > 0 => $"非空字符串: {s}",
int i when i >= 100 => $"大整数: {i}",
Person p when p.Age >= 18 => $"成年用户: {p.Name}",
null => "输入为空",
_ => "其他类型或默认值"
};
-
when后是任意布尔表达式,但别放耗时操作(如 DB 查询),它在匹配路径上同步执行 - 属性模式(如
Person p)自动做非空检查,p在分支内一定是非null - 所有分支必须返回相同类型;
null =>分支也得返回string,不能只写null => throw
枚举和字符串字面量映射:怎么防漏值、避硬编码
编译器会强制覆盖所有已知取值,但前提是类型可穷举且你没绕过检查:
string desc = day switch
{
DayOfWeek.Saturday or DayOfWeek.Sunday => "休息日",
DayOfWeek.Monday => "周一启动日",
_ => "工作日" // 必须有,否则编译失败
};
- 用
or组合多个枚举值合法,但漏掉任意一个(如Friday)且没写_ =>,就触发CS8509 - 字符串字面量匹配(如
"apple")是严格全等,不是子串或正则;需要模糊匹配请改用is+ 守卫,别硬塞进switch - 若枚举是可空的(
DayOfWeek?),必须单独处理null =>分支,_无法覆盖null
property pattern 怎么写才真正按字段值匹配
属性模式不是“语法糖”,它会真实访问属性(可能触发 getter),且支持嵌套和组合:
var status = person switch
{
Person { Age: >= 18, Name: not null } => "valid adult",
Person { Age: "minor",
_ => "invalid"
};
-
Age: >= 18是关系模式,Name: not null是常量模式,它们必须嵌套在Person { ... }内使用 - 嵌套 property pattern 合法:如
Order { Customer: { IsPremium: true } } => "priority" - 每次匹配都会调用属性 getter;如果
Age是计算属性且含副作用,要小心重复执行
最易忽略的一点:switch 表达式要求所有可能输入路径都有对应分支,而这个“可能”由编译器静态推断——对 object 或基类引用,它无法知道子类有哪些,所以必须靠 _ => 收尾;但对 sealed record 或 enum,漏一个就编译不过,这不是限制,是保护。











