Chapter 1. Introducing C# and .NET
覆盖C#设计保证、CLR/BCL/runtime分层、版本历史与C# 10/.NET 6能力矩阵,建立语言、API、运行时和部署证据。
学习目标
- 能比较Object Orientation、Type Safety、Memory Management与Platform Support各自保证和不保证的内容
- 能绘制C#、compiler、CLR、BCL、runtime、TFM与application model分层,定位feature failure属于哪层
- 能设计C# 10/.NET 6兼容矩阵,用compile、publish和target-machine运行证据验证升级
为什么第一章先拆开Language与Platform
C#不是“.NET的另一个名字”。C#定义source syntax、type rules和semantics;compiler把source生成IL/metadata或其他target artifact;CLR负责load、verify、JIT与GC;BCL提供string、collections、I/O等APIs;ASP.NET Core、desktop与MAUI等application models再建立更高层约定。排错若把这些混在一起,就会把“编译器不认识syntax”“reference assembly无API”“目标机缺runtime”都叫成C#版本问题。
先预测:项目设置LangVersion 10就能调用所有.NET 6 API吗;GC会及时关闭socket吗;type-safe表示绝不发生InvalidCastException吗;IL相同就能在所有OS运行吗;self-contained publish不再依赖native platform吗。答案都是否。
↡把source language、compiler、runtime、base libraries与application model分开定位责任和版本的结构。Object Orientation
C#以class/struct、encapsulation、inheritance、interface和runtime polymorphism支持对象建模。Virtual/interface call根据runtime type dispatch;static type决定可见members与overload resolution。Object orientation帮助把state与invariants收拢到owner,但可变alias、deep inheritance和hidden side effects仍需设计约束,不会因用了class自动消失。
IFormatter formatter = new JsonFormatter();
string payload = formatter.Format(order); // runtime dispatch
// Overload selection仍以compile-time types为基础。
Print((object)order);Composition通常比继承更容易限定lifetime与替换。Interface contract要说明thread safety、nullability、exception和resource ownership;否则“面向对象”只提供syntax。测试同时覆盖compile-time overload与runtime dispatch,防止把二者混成同一机制。
Type Safety
Type Safety让compiler和CLR限制不兼容operation:每个expression有type,conversion、generic constraint和member access在明确规则下发生。它减少memory corruption与shape guessing,但并不表示运行时永不失败。Explicit cast、array covariance、dynamic、reflection和interop都可能把检查推迟,nullable warning也依赖项目开启与annotation质量。
↡Compiler与CLR按static/runtime type规则约束operations,并把绕过检查的boundary显式暴露。object value = "42";
string text = (string)value; // checked at runtime
int number = int.Parse(text); // type-safe, but input may be invalid
// dynamic/reflection/interop把部分检查推迟到运行时。“编译通过”只证明static rules成立,不证明input valid、API available或invariant正确。Boundary tests应覆盖invalid cast、null、dynamic binder、serialization与native marshaling;domain constructors再把合法业务状态收窄。
Memory Management
Managed object由GC根据reachability回收,程序通常不手工free。GC roots包括static、stack/reference、handle等;reachable不等于仍有业务价值,event subscription、timer和cache可造成managed leak。GC也不管理文件句柄、socket、transaction等稀缺resource的及时释放,它们依赖IDisposable/await using与owner lifetime。
↡GC按reachability管理managed memory,而IDisposable按lexical/owner scope及时释放external resource的双重生命周期。Platform Support
C#/.NET支持多OS与architectures,因为managed IL由目标runtime执行,BCL提供跨平台contract。但platform-neutral不是platform-identical:filesystem casing/path、timezone、globalization、native library、COM、Windows Event Log和UI stack都可能不同。Target Framework Moniker决定compile-time API surface,Runtime Identifier影响publish assets,OS guards表达运行时条件。
Cross-platform验收在target OS/RID真正运行,不只在开发机编译。Path、encoding、culture、line endings、TLS和native dependency进入matrix;platform-specific capability放在adapter后,并用OperatingSystem.IsWindows()等guard和analyzer attribute约束调用。
切换object、type-safe、managed与portable
CLRs, BCLs, and Runtimes
CLR是Common Language Runtime:load assemblies、validate metadata、JIT methods、manage exceptions/threads/GC。BCL是Base Class Library contracts和implementations。Runtime distribution把CLR、BCL和host组合成可部署产品;reference assemblies则供compiler决定可调用API,不是运行时implementation。
同一C# compiler可用新syntax target旧TFM,只要lowering不需要缺失runtime/API;反之旧syntax也可调用新BCL。Feature analysis必须写四列:syntax first version、compiler lowering、BCL dependency、runtime/JIT behavior。比如file-scoped namespace主要是source transformation,而某个新API需要net6 reference和target runtime。
↡由CLR执行引擎、BCL API surface和host/deployment组成的可运行.NET产品版本。切换language、runtime、library与app model
A Brief History of C#
C#从早期object-oriented/type-safe managed language,逐步加入generics、nullable values、iterators、LINQ/lambdas、dynamic、async/await、pattern matching、nullable references、records与top-level/global namespace conveniences。历史意义不在背年份,而在理解feature如何叠加:LINQ依赖generics/delegates/lambdas/extensions,async依赖Task/awaiter protocol,records依赖已有type/equality机制。
版本历史还提醒兼容性:compiler、language和runtime发布节奏可分离;某feature只有syntax变化,某feature需要runtime recognition或BCL types。Legacy project升级时先锁定当前 TFM/LangVersion/SDK,再逐项迁移,不让IDE默认升级掩盖生产约束。
What's New in C# 10
C# 10的代表能力包括global using、file-scoped namespace、record structs、struct parameterless constructors与field initializers、extended property patterns、lambda improvements、CallerArgumentExpression、constant interpolated strings等。它们分属ceremony reduction、data modeling、pattern/API diagnostics,不能用“现代语法”一概而论。
迁移要按observable semantics检查。Global using会改变name lookup/ambiguity;record struct值语义与copy成本不同于record class;lambda inference可能影响overload;CallerArgumentExpression是diagnostic text,不是可信identity。每项都用compile fixtures和API contract tests确认。
↡把LangVersion、TFM/reference assemblies、runtime host与RID/OS放在同一表中验证feature可用性的门禁。切换C# 10、.NET 6、older target与deployment
Upgrade and deployment gate
Repository应通过global.json或CI image锁定SDK,项目显式设置TargetFramework/LangVersion/Nullable。Package restore lock与runtimeconfig纳入artifact;部署选择framework-dependent或self-contained,并记录size、patching和roll-forward tradeoff。多target library需要为每个TFM编译,不能只测最高版本。
升级验收包括source/ABI/API compatibility、serialization schema、reflection behavior、culture/platform和performance。若只在IDE“能运行”,没有目标机runtime/RID evidence,就未完成平台迁移。
本章回顾:每个Feature都有四个版本坐标
- C#提供object orientation与type rules,但不自动保证domain invariant或无runtime failure。
- GC管理managed memory reachability,IDisposable管理external resource lifetime。
- CLR、BCL、runtime distribution和application model有不同职责。
- Cross-platform需要验证OS/RID/native差异,不等于相同artifact无条件运行。
- C# 10 feature通过LangVersion、TFM、runtime和deployment matrix验收。
练习
问题 1:为什么LangVersion=10仍可能无法编译某段示例?
问题 2:怎样证明一个library真正cross-platform?
问题 3:GC与Dispose的测试证据有什么不同?
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- language-platform boundary
- type-safety envelope
- managed-resource split
- runtime distribution
- feature compatibility matrix