Chapter 12. Deconstruction and pattern matching
覆盖tuple与nontuple deconstruction、C# 7.0 constant/type/var patterns、is与switch语义、scope、case order和使用边界。
学习目标
- 能解释tuple和custom Deconstruct如何按arity、out types与position绑定,并区分producer member names与consumer local names
- 能分析C# 7 constant、type和var patterns的match、binding、null与scope规则,在is表达式中避免未赋值或混淆
- 能设计pattern switch的ordered decision table,用case order、when guards、null/default policy和tests证明分类完整性
机制总览
Chapter 12. Deconstruction and pattern matching:机制路径
- 1
从Shape验证开始理解Deconstruction与Pa…
Deconstruction让consumer一次把一个compound value拆到多个locals;pattern matching把runtime test与成功后的typed binding放在同一语法中。二者都减少重复access/cast,却也把protocol selection、s…
- 2
Deconstruction of tuples
Tuple deconstruction按position展开: var (id, total) = summary; 中的local names由consumer选择,不必等于tuple element names。显式types、 var 混合形式受版本语法限制;discard 表示有意识地忽略某一position,但仍参与shape/arity匹配。
- 3
Deconstruction of nontuple ty…
Class或struct可提供accessible instance Deconstruct(out T1, out T2, ...) ;extension method也可给不能修改的type增加consumer view。Compiler按name、arity与applicable overlo…
章级决策实验
Chapter 12. Deconstruction and pattern matching:机制与证据
切换《Chapter 12. Deconstruction and pattern matching》的三个关键教学阶段,先解释机制,再用运行与失败证据验证结论。
选择推理阶段
当前阶段 · 从Shape验证开始理解Deconstruction与Pa…
Deconstruction让consumer一次把一个compound value拆到多个locals;pattern matching把runtime test与成功后的typed binding放在同一语法中。二者都减少重复access/cast,却也把protocol selection、s…
可核验证据
以明确的 LangVersion 与目标框架构建「从Shape验证开始理解Deconstruction与Pa…」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
学完《Chapter 12. Deconstruction and pattern matching》后,应能从输入和前置条件推导状态变化,并用可重复的构建、运行或边界测试证明结果。
失效—证据矩阵
Chapter 12. Deconstruction and pattern matching:失效与核验
从Shape验证开始理解Deconstruction与Pa…
典型失效
若解释「从Shape验证开始理解Deconstruction与Pa…」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「从Shape验证开始理解Deconstruction与Pa…」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
Deconstruction of tuples
典型失效
若解释「Deconstruction of tuples」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「Deconstruction of tuples」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
Deconstruction of nontuple ty…
典型失效
若解释「Deconstruction of nontuple ty…」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「Deconstruction of nontuple ty…」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
从Shape验证开始理解Deconstruction与Pattern
Deconstruction让consumer一次把一个compound value拆到多个locals;pattern matching把runtime test与成功后的typed binding放在同一语法中。二者都减少重复access/cast,却也把protocol selection、scope与control flow压进短表达式。掌握它们不能只记syntax,必须追踪“哪个producer提供shape、何时match、哪些变量在何处definitely assigned”。
先预测:deconstruction local names是否必须等于tuple element names;任意有两个properties的type是否自动可拆;type pattern是否匹配null;var pattern是否可能失败;switch pattern cases是否按最具体type自动排序。答案依次是“否、否、否、通常不失败、否”。
Deconstruction of tuples
Tuple deconstruction按position展开:var (id, total) = summary;中的local names由consumer选择,不必等于tuple element names。显式types、var混合形式受版本语法限制;discard _表示有意识地忽略某一position,但仍参与shape/arity匹配。
Assignment deconstruction可写入已有variables,右侧expressions先按规定求值,再分配到左侧locations。不要依赖names修正position;两个同type元素交换仍是semantic bug。Nested tuples产生nested deconstruction shape,评审时最好画出position tree。
(int orderId, decimal total) summary = LoadSummary();
var (id, amount) = summary;
(amount, id) = (amount + 10m, id + 1);
var (_, tax) = CalculateTotals();Deconstruction of nontuple types
Class或struct可提供accessible instance Deconstruct(out T1, out T2, ...);extension method也可给不能修改的type增加consumer view。Compiler按name、arity与applicable overload选择方法,不是看到properties就自动拆。多个相近overloads可能造成ambiguity或随新增overload改变binding,应保持shape数量和语义稳定。
Deconstruct表达“从一个value观察出多个components”,不等于constructor inverse。Rounded、normalized或derived outputs可能无法重建原对象;若需要round-trip,必须单独声明并测试law。Public Deconstruct也是API surface,新增同arity overload要做source compatibility review。
public sealed class Money
{
public decimal Amount { get; }
public string Currency { get; }
public void Deconstruct(out decimal amount, out string currency) =>
(amount, currency) = (Amount, Currency);
}切换tuple、instance、extension与discard
Introduction to pattern matching
Pattern把两件事合并:检查input是否符合某个shape,并在成功路径绑定information。C# 7.0的核心是constant、type和var patterns;它还没有Chapter 15所预览的recursive property/positional patterns。版本边界很重要,否则会误以为所有现代pattern syntax都属于本章。
Pattern variable受definite assignment与control-flow analysis控制。if (value is Order order)的true branch中order可用;在&&右侧也可用,因为只有match成功才evaluation。与||组合时要逐path检查,不能靠视觉猜scope和assignment。
Patterns available in C# 7.0
Constant pattern比较constant,包括null;type pattern先检查runtime type兼容并在成功时绑定typed variable,null不会匹配任何type pattern;var pattern绑定input为新variable,通常总是成功,input为null也会被捕获。_在这些历史语境中要根据具体syntax判断discard或identifier,不能把所有underscore一概当现代discard pattern。
if (input is Order order && order.Total > 0m)
{
Process(order);
}
else if (input is null)
{
Reject("missing");
}切换constant、type、var与guard
Using patterns with the is operator
传统代码常先is再cast,或用as后检查null。Type pattern一次完成test与binding,减少重复lookup和race-like inconsistency。它仍只表达runtime type兼容;business validity要在后续guard或domain method中判断。
Negation在C# 7时代通常写成!(value is Order order),变量scope与definite assignment容易让代码难读。Later is not属于后续版本。教学和维护时应按项目LangVersion选择真实可用syntax,而不是把现代写法倒灌到第四版chapter。
Using patterns with switch statements
C# 7扩展switch,使case可用type patterns和when guards,不再只限constant labels。Cases是按source order评估的decision rules;broad base case放在derived case前可能让后者unreachable。Guard只在前面的pattern成功后运行,适合表达positive total、specific state等额外condition。
Null不会匹配type pattern,因此需要case null或明确default policy。Default不一定表示错误:可以记录unknown subtype、返回fallback或抛带context的异常,但必须有可验收的ownership。分类规则不断增长时,优先把case matrix写成table和tests。
切换specific、broad、null与default
Thoughts on usage
Pattern matching适合type-driven behavior、parser result分类和明确closed-ish hierarchy。若switch散落在很多modules,每加subtype都要多处修改,说明behavior可能更适合virtual dispatch、visitor或domain-owned method。反过来,单一consumer对外部types做分类时,central switch比污染每个type更合理。
Deconstruction适合consumer只需要少量components且position meaning稳定。若出现五六个outputs、多个同type values或必须先validate invariant,return nominal result更清楚。短syntax应让decision model更集中,不应让domain rules藏在case order与positions里。
本章回顾:Shape、Binding与Control Flow必须一起验证
- Tuple deconstruction按position;custom types通过明确的Deconstruct protocol提供shape。
- Consumer local names不改变producer shape,discard也不取消arity要求。
- C# 7.0 patterns包括constant、type和var,各自的null与failure行为不同。
- Is pattern variable可用性由control flow和definite assignment决定。
- Switch pattern是ordered classifier;case order、guards、null与default共同形成contract。
练习
问题 1:为Point新增两个同arity Deconstruct overload有什么风险?
问题 2:如何证明if (x is Order o && o.Total > 0)中的o安全,而换成||后不一定安全?
问题 3:支付分类switch怎样防止新subtype静默落入错误分支?
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- deconstruction protocol
- pattern variable scope
- runtime type refinement
- guard ordering
- total classification
原版目录概念补充核对
以下条目补齐官方目录中容易被示例主线掩盖的概念。它们不重复罗列目录,而是明确每项概念的机制、适用边界和验收证据。
Deconstruction of nontuple types:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Deconstruction of nontuple types必须分清语言规范、编译器实现、运行时行为与基础类库 API 四层责任。固定 C# 语言版本和目标框架,用正向/负向编译案例、必要的 IL 或运行轨迹以及版本对照验证结论。
Introduction to pattern matching:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Introduction to pattern matching涉及值的存储位置、复制语义与生命周期,语法简洁不代表没有别名或逃逸限制。准备可编译和应被编译器拒绝的样本,结合 IL、分配计数或地址/修改轨迹核对复制、别名与边界。
Patterns available in C# 7.0:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Patterns available in C# 7.0涉及值的存储位置、复制语义与生命周期,语法简洁不代表没有别名或逃逸限制。准备可编译和应被编译器拒绝的样本,结合 IL、分配计数或地址/修改轨迹核对复制、别名与边界。
Using patterns with the is operator:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Using patterns with the is operator涉及值的存储位置、复制语义与生命周期,语法简洁不代表没有别名或逃逸限制。准备可编译和应被编译器拒绝的样本,结合 IL、分配计数或地址/修改轨迹核对复制、别名与边界。
Using patterns with switch statements:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Using patterns with switch statements涉及值的存储位置、复制语义与生命周期,语法简洁不代表没有别名或逃逸限制。准备可编译和应被编译器拒绝的样本,结合 IL、分配计数或地址/修改轨迹核对复制、别名与边界。
Thoughts on usage:机制、边界与证据
Chapter 12. Deconstruction and pattern matching中的Thoughts on usage必须分清语言规范、编译器实现、运行时行为与基础类库 API 四层责任。固定 C# 语言版本和目标框架,用正向/负向编译案例、必要的 IL 或运行轨迹以及版本对照验证结论。