模式匹配不是语法糖,而是C#编译器在类型安全和作用域控制上的实质性约束:is后接的是“声明+约束”组合体,变量仅在匹配成功的作用域内有效,编译器强制隔离,杜绝误用。

模式匹配不是语法糖,它是 C# 编译器在类型安全和作用域控制上做的实质性约束——is 后面跟的不是“判断条件”,而是“声明+约束”的组合体,变量只在匹配成功的作用域内有效。
什么时候该用 is + 声明模式,而不是 as + 空值检查
当你需要同时做类型检查和变量提取时,is 声明模式比 as 更安全、更简洁。它避免了 as 后还要手动判空,也绕开了重载 == 可能带来的语义歧义。
-
as仅做引用/可空类型转换,失败返回null或default,不提供作用域隔离 -
is T x一旦匹配失败,x在当前作用域根本不可见,编译器直接报错,杜绝误用 - 对值类型(如
int?)用as会编译失败,但is int number完全合法 - 示例:
if (obj is string s && s.Length > 0)——s在整个&&右侧都可用,且只在匹配成功时存在
switch 表达式里怎么写嵌套属性模式
属性模式支持递归,但必须确保路径上的每个成员都非空,否则运行时抛 NullReferenceException。编译器不会帮你做空保护,得靠 is not null 或 ?. 配合。
- 错误写法:
person is { Address.City: "Beijing" }—— 如果Address是null,直接崩 - 正确写法:
person is { Address: { City: "Beijing" } },但前提是Address类型已知且非空;若可能为null,应拆成两层:person is { Address: not null } and { Address.City: "Beijing" } - 更稳妥的写法是结合逻辑模式:
person is { Address: { City: "Beijing" } } or { Address: null },但注意这会改变语义 - 属性名必须拼写准确,且对应属性需有 public getter,私有字段不参与匹配
为什么 is not null 比 != null 更推荐
因为 != null 依赖类型是否重载了 == 运算符,而 is not null 是语言级空检查,不调用任何用户代码,行为确定、性能一致。
- 对自定义类,若重载了
==但没处理null,obj != null可能抛NullReferenceException -
is not null对所有引用类型、可空值类型(T?)都适用,且编译期就能验证合法性 - 它还能和类型模式组合:
if (str is not null and string s),一次完成非空 + 类型提取 - 注意:
is not null对非可空引用类型(启用了 nullable reference types)是冗余的,编译器会警告
常量模式和关系模式混用时的优先级陷阱
C# 的模式优先级规则不按数学直觉走:is >= 18 and 是合法的,但 <code>is 18 or 19 or 20 不合法 —— or 不能用于多个常量,必须改用逗号分隔的列表模式或 switch。
- 关系模式(
>=,等)只能出现在属性模式或类型模式内部,不能单独用于 <code>is右侧 - 想匹配多个离散值,用
switch最自然:age switch { 18 or 19 or 20 => "teen", _ => "other" } - 在
if中想模拟多值匹配,得用is 18 or is 19,但这是两个独立判断,不是单个模式 - 列表模式(C# 11+)支持
is [18, 19, 20],但仅适用于IReadOnlyList<t></t>或数组,不适用于单个整数
最容易被忽略的是:所有模式匹配都发生在编译时类型系统约束下,运行时对象的实际类型若与编译时类型无继承/实现关系,再复杂的嵌套模式也匹配不上——别指望靠模式匹配绕过类型系统的基本规则。


















