Chapter 3. C# 3: LINQ and everything that comes with it
覆盖Automatically implemented properties、Implicit typing、Initializers、Anonymous types、Lambda、Extension methods、Query expressions与LINQ整合。
学习目标
- 能分析auto property、implicit local、initializer和anonymous type的compiler output、evaluation order与contract scope
- 能比较lambda转换为delegate或expression tree,并判断extension/overload resolution选择的实际调用目标
- 能推导query clauses到standard operator calls,复现Enumerable/Queryable与terminal execution差异
机制总览
Chapter 3. C# 3: LINQ and everything that comes with it:机制路径
- 1
为什么C 3的许多小Feature最终汇聚成LINQ
C 3不是只加入query syntax。Auto property让data carrier简洁, var 让anonymous type可命名于local scope,initializer让sample data易构建,lambda提供inline behavior,extension met…
- 2
Automatically implemented pro…
Auto property由compiler生成backing field与accessors,public contract仍是property。它适合没有额外validation的state;一旦需要invariant、computed value或observable mutation,就显式…
- 3
Implicit typing
var 要求initializer并在compile time得到exact static type;之后赋值和member resolution都按该type进行。它使anonymous type与复杂generic query可用,不等于 dynamic 。当右侧清楚揭示type时减少重复;当m…
章级决策实验
Chapter 3. C# 3: LINQ and everything that comes with it:机制与证据
切换《Chapter 3. C# 3: LINQ and everything that comes with it》的三个关键教学阶段,先解释机制,再用运行与失败证据验证结论。
选择推理阶段
当前阶段 · 为什么C 3的许多小Feature最终汇聚成LINQ
C 3不是只加入query syntax。Auto property让data carrier简洁, var 让anonymous type可命名于local scope,initializer让sample data易构建,lambda提供inline behavior,extension met…
可核验证据
以明确的 LangVersion 与目标框架构建「为什么C 3的许多小Feature最终汇聚成LINQ」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
学完《Chapter 3. C# 3: LINQ and everything that comes with it》后,应能从输入和前置条件推导状态变化,并用可重复的构建、运行或边界测试证明结果。
失效—证据矩阵
Chapter 3. C# 3: LINQ and everything that comes with it:失效与核验
为什么C 3的许多小Feature最终汇聚成LINQ
典型失效
若解释「为什么C 3的许多小Feature最终汇聚成LINQ」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「为什么C 3的许多小Feature最终汇聚成LINQ」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
Automatically implemented pro…
典型失效
若解释「Automatically implemented pro…」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「Automatically implemented pro…」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
Implicit typing
典型失效
若解释「Implicit typing」时混淆语言规范、编译器降级、运行时和类库责任,版本变化后就会把实现细节误当作 C# 语义保证。
核验证据
以明确的 LangVersion 与目标框架构建「Implicit typing」的正反案例,并用编译诊断、生成 IL、运行轨迹或分配数据核对实际边界。
为什么C# 3的许多小Feature最终汇聚成LINQ
C# 3不是只加入query syntax。Auto property让data carrier简洁,var让anonymous type可命名于local scope,initializer让sample data易构建,lambda提供inline behavior,extension methods让operators看似属于source,expression tree让provider读取code structure。缺少任意一环,统一query experience都会更笨重。
先预测:var是否改变runtime type;object initializer是否绕过constructor;lambda是否天然是delegate;query expression是否由runtime解释。答案都是否。
Automatically implemented properties
Auto property由compiler生成backing field与accessors,public contract仍是property。它适合没有额外validation的state;一旦需要invariant、computed value或observable mutation,就显式实现accessor。Compiler-generated field name不是reflection/serialization的stable contract。
Property initializer与init/required等是后续版本演进,不能倒写成C# 3原始能力。现代代码可使用它们,但应区分“原书解释auto property”与“当前API选择immutability”。
Implicit typing
var要求initializer并在compile time得到exact static type;之后赋值和member resolution都按该type进行。它使anonymous type与复杂generic query可用,不等于dynamic。当右侧清楚揭示type时减少重复;当method name隐藏precision或abstraction时显式type更好。
Object and collection initializers
Object initializer先调用constructor,再按source order调用setters/field assignments;collection initializer翻译为一系列Add calls。若中途setter/Add抛异常,对象可能已经产生side effects但expression未返回。Constructor仍应建立最低valid invariant,initializer不是required-state验证的替代。
var order = new Order("A-42")
{
Customer = customer,
Priority = Priority.High,
};Anonymous types
Anonymous type提供compiler-generated immutable properties、structural equality与useful ToString,适合local projection/composite key。Its identity受property names、types与order影响,不能在public signature中直接命名,也不应跨assembly当wire contract。需要长期domain meaning时提升为named record/class。
切换property、var、initializer与anonymous type
Lambda expressions
Lambda没有独立runtime type;它必须转换到compatible delegate或expression-tree target。Delegate路径生成可执行method并可能生成closure,expression path构建描述parameters、operations与calls的object graph。Provider只能翻译其理解的nodes,不能执行任意C#。
Overload resolution会根据candidate target types尝试lambda conversion,因此相同text在不同call site得到不同meaning。Statement lambda通常不能直接成为expression tree;optional/ref等signature也受版本规则限制。遇到ambiguity时显式声明target type比cast result更清楚。
Extension methods
Extension method是带this首参数的static method,并由using namespace与receiver static type参与compile-time resolution。Instance member优先,extension没有virtual dispatch,也不能访问private state。它让source.Where(...)形成fluent vocabulary,但真正调用仍是Enumerable.Where(source, ...)或Queryable.Where(...)。
Func<Order, bool> local = order => order.Total > 100m;
Expression<Func<Order, bool>> remote = order => order.Total > 100m;切换delegate、expression、extension与overload
Query expressions
Query expression是compiler translation syntax。from/where/select映射到SelectMany、Where、Select等method calls;transparent identifiers帮助多from/let保留range variables。Translation发生在compile time,不是SQL parser嵌入C#。
Query syntax在join、group、continuation等relational shape上常更清楚;method syntax对短pipeline或无query-clause对应的operators更直接。二者可混用,选择可读性而非performance myth,因为最终operator chain才决定behavior。
The end result: LINQ
LINQ统一operators与lambda/query composition,不统一data source。IEnumerable<T>接收delegates并在process内enumerate;IQueryable<T>接收expression trees并让provider翻译。Deferred/eager、ordering、null semantics、string comparison与supported methods都由operator/provider contract决定。
var query =
from order in orders
where order.Total > minimum
orderby order.CreatedAt
select new { order.Id, order.Total };切换where、select、join/group与完整LINQ
本章回顾:LINQ是Feature Convergence而非单一语法
- Auto property、var、initializer与anonymous type共同降低data shaping ceremony。
var保留exact static type;initializer仍在constructor之后按顺序mutation。- Lambda由target type决定delegate或expression tree,capture与translation contract不同。
- Extension按compile-time static resolution,instance member优先且没有virtual dispatch。
- Query expression映射到methods;Enumerable/Queryable与terminal决定执行引擎、时机和成本。
练习
问题 1:为何anonymous type、var与LINQ projection常一起出现?
问题 2:同一lambda传给List和EF query,为何测试策略不同?
问题 3:如何判断query syntax与method syntax的选择没有改变行为?
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- feature convergence
- anonymous structural shape
- target-typed lambda conversion
- extension binding
- query expression translation
原版目录概念补充核对
以下条目补齐官方目录中容易被示例主线掩盖的概念。它们不重复罗列目录,而是明确每项概念的机制、适用边界和验收证据。
Object and collection initializers:机制、边界与证据
Chapter 3. C# 3: LINQ and everything that comes with it中的Object and collection initializers涉及值的存储位置、复制语义与生命周期,语法简洁不代表没有别名或逃逸限制。准备可编译和应被编译器拒绝的样本,结合 IL、分配计数或地址/修改轨迹核对复制、别名与边界。
Lambda expressions:机制、边界与证据
Chapter 3. C# 3: LINQ and everything that comes with it中的Lambda expressions必须分清语言规范、编译器实现、运行时行为与基础类库 API 四层责任。固定 C# 语言版本和目标框架,用正向/负向编译案例、必要的 IL 或运行轨迹以及版本对照验证结论。
The end result: LINQ:机制、边界与证据
Chapter 3. C# 3: LINQ and everything that comes with it中的The end result: LINQ必须分清语言规范、编译器实现、运行时行为与基础类库 API 四层责任。固定 C# 语言版本和目标框架,用正向/负向编译案例、必要的 IL 或运行轨迹以及版本对照验证结论。