模式匹配是C#编译器强约束的类型安全机制,is后为“声明+约束”,变量仅在匹配成功时存在;应优先用is T x而非as+null检查,因其提供作用域隔离且支持值类型。

模式匹配不是“更高级的 if”,它是 C# 编译器在类型安全和作用域控制上做的硬性约束——is 后面跟的不是条件,而是「声明 + 约束」;变量只在匹配成功时存在,编译器直接禁止跨作用域访问。
什么时候该用 is T x 而不是 as + null 检查
as 只做转换,失败返回 null 或 default,但不提供作用域隔离,也不处理值类型(比如 int? 用 as int? 会编译失败);is int? i 则完全合法,且 i 在后续代码中天然非空、类型确定。
-
obj is string s && s.Length > 0:s 在整个&&右侧都可用,且编译期就保证非 null -
obj as string返回 null 后还需手动判空,多一步且易漏 - 对重载了
==的类,obj != null可能抛NullReferenceException;is not null是语言级检查,不调用用户代码
switch 表达式里怎么写嵌套属性模式
属性模式支持递归,但编译器不做空保护。路径上任一环节为 null,运行时直接崩——比如 person is { Address: { City: "Beijing" } },若 Address 是 null,就会触发 NullReferenceException。
- 稳妥写法是拆成两层:
person is { Address: not null } and { Address.City: "Beijing" } - 或用逻辑模式组合:
person is { Address: { City: "Beijing" } } or { Address: null },但注意这会改变语义(后者分支也会命中) - 属性名必须拼写准确,且对应成员要有 public getter;私有字段、字段(field)不参与匹配
关系模式和常量模式混用的优先级陷阱
C# 不按数学直觉解析关系表达式。is >= 18 合法,但 is 18 or 19 or 20 非法——or 不能用于多个常量值。
- 多个离散值要用逗号分隔的列表模式:
is 18 or 19 or 20❌ → 改成is 18 or 19 or 20仍错,正确是is (18 or 19 or 20)?不,C# 不支持这种语法;应改用is 18 or is 19 or is 20(拆成多个 case),或用范围:is >= 18 and - 关系模式(
>=、等)只能出现在属性模式或类型模式内部,不能单独用于 <code>is后面 - 在
switch表达式中,when子句里避免副作用(如修改状态),因为匹配顺序不保证执行顺序,JIT 可能优化掉未命中的分支
var 模式和弃元 _ 的真实行为
obj is var x 不是“万能匹配”,它等价于 obj != null(仅对引用类型有意义);对值类型(如 default(int) 即 0)永远不成立,因为值类型不能为 null。
-
obj is _是恒真判断,几乎没用;真正该用弃元的是解构场景,比如(x, _) is (1, _) - 在
switch中过度依赖_ =>会掩盖新增子类型——比如你处理Shape的子类,后来加了Triangle,但_ =>把它吞掉了,编译器无法提醒你遗漏 - 开启可空引用类型(NRT)后,
string?和string在模式中表现不同:is string s不匹配null,而is string? s可以匹配并绑定null
最常被忽略的一点:模式匹配的“穷尽性检查”只在 sealed 类型层级下严格生效;如果基类没标记 sealed,编译器不会警告你漏掉未知派生类型——这时候靠 _ => 并不安全,得结合文档或运行时日志兜底。


















