资讯动态

C#核心术语速查:从类型系统到异步编程的实用指南

发布时间:2026/10/13 19:38:03 来源:尧图企业网站定制
1. 为什么每年都要重新整理一份C#术语表C#这门语言走到今天已经有二十多个年头了从最初的只能写写Windows桌面程序到现在横跨Web、云原生、游戏、移动端甚至嵌入式语法特性也从一个相对保守的面向对象语言变成了带模式匹配、记录类型、异步流等现代特性的多范式语言。作为一个经常在项目里切换技术栈的人我最大的感受是很多C#的术语看起来眼熟但真要让你准确说出它的含义、适用场景、以及它跟隔壁相关概念的区别往往要愣一下。比如“委托”和“事件”是什么关系“协变”和“逆变”到底解决了什么问题“托管堆”和“栈”上的数据在生命周期上有什么本质差异这些术语不搞清楚读源码、查报错、做Code Review的时候都容易吃亏。举个很简单的例子报错信息里出现“CS8175”或者“Cannot use ref local inside an iterator”如果不懂“迭代器”和“ref struct”这些概念光靠搜索引擎来回折腾可能就要花掉一下午。而如果你脑子里有一张清晰的术语地图基本上扫一眼报错关键词就能定位到是哪个语法特性在使用上出了问题。这篇文章不想写成一本C#字典而是想整理一份“真正会被日常开发反复用到”的术语速查表按类别拆开每个术语附上简明解释、代码示意、以及和我一起踩过坑之后的对比说明。你可以把它当作案头手册也可以当作排查问题时的思维索引。适合的读者包括刚开始学C#但被各种名词绕晕的初学者、从其他语言转过来的老手、以及带团队时需要在CR里解释概念的技术负责人。我尽量用大白话让每个词都不只是“知道”而是“用得上”。2. C#类型系统的核心术语先把地基夯结实2.1 值类型与引用类型一句话理清“数据放哪”的问题C#里最基础、也是最容易带偏新手的一组概念就是值类型Value Type和引用类型Reference Type。我们说“int是值类型”“class是引用类型”但真正理解这对术语的含义要落到内存布局上值类型的变量直接存着数据本身引用类型的变量存的是一个指向堆上对象的引用可以粗浅理解为地址。int a 10; int b a; b 20; // a 还是 10b 是 20两者各存各的 MyClass x new MyClass { Value 1 }; MyClass y x; y.Value 99; // x.Value 也变成 99因为 x 和 y 指向的是堆上同一个对象做赋值、传参、集合存取时搞清楚当前操作的对象是值类型还是引用类型是判断结果是否符合预期的前提。C#里常见值类型有int、double、bool、char、struct、enum常见引用类型有class、interface、delegate、string、array。注意string虽然是一个引用类型但它的不可变性Immutable让它表现得很多时候像一个值类型这也是许多新手初期困惑的来源。我的习惯是如果遇到“改了变量A为什么B也跟着变”的问题第一反应就是检查它是不是引用类型然后看是不是在某个地方共享了实例。2.2 装箱与拆箱一次隐形的性能损耗装箱Boxing是把值类型转换成object或接口类型的过程拆箱Unboxing则相反是把object转回原来的值类型。这个过程会带来额外的内存分配和复制开销在频繁场景下可能成为性能瓶颈。int num 42; object boxed num; // 装箱堆上分配一个新对象 int unboxed (int)boxed; // 拆箱再从堆上取回早期写C#的人多少都被ArrayList坑过往里面塞int时每个int都会装箱取出来还要拆箱。后来泛型List 出现这个问题才得到了根治。所以现在写代码时我基本只在需要把值类型当成多态对象处理时比如某些反射场景、老式接口调用才会接受装箱代价日常集合一律用泛型。2.3 var、dynamic与匿名类型三个容易混淆的“类型推断”角色var编译期推断类型运行时类型是确定的。var x 10;编译器其实把x当作int。dynamic运行时才解析类型编译期不做检查。适合与动态语言互操作但错误使用容易丢失编译期安全检查。匿名类型Anonymous Typenew { Name 张三, Age 30 }不显式定义类编译器自动生成一个只读类型常用于LINQ投影。这三个概念经常被拿来对比我总结一句话var是“写的时候省事”dynamic是“运行的时候再说”匿名类型是“临时攒一个类型来用”。日常开发推荐优先用var和匿名类型dynamic只在跨层调用、COM互操作、或者接收JSON动态字段这类场景使用过度使用dynamic会让后期重构非常痛苦。2.4 可空值类型与空值传播跟null死磕的语法工具可空值类型Nullable 用int?表示意思是“值类型也能表达缺失”。空值传播Null Propagation用?.和??操作符一个用于安全访问成员一个用于提供默认值。int? maybeNumber null; int realNumber maybeNumber ?? 0; // 如果为null就拿0 string name person?.Name ?? 未知;这里要特别注意??和?:三元运算符看着像、实际完全不同。??是空合并运算符只有在左侧为null时才取右侧值?:是条件运算符根据布尔条件二选一。还有后续C# 8引入的??意思是“如果左值为null就赋值”在写缓存、延迟初始化时非常实用比如data ?? LoadData();。理解了这套空值工具链代码里满天飞的if (xx ! null)就能少一大半。3. 面向对象机制术语类、接口与多态的全方位梳理3.1 类、对象、结构体、记录类型创建自定义类型的四种姿势C#里能自定义的类型载体有好几种class、struct、record、record struct。它们各有各的语义倾向class引用类型面向对象主力支持继承和多态。struct值类型适合表示轻量级数据比如坐标、颜色、范围不适合频繁复制的大对象。record引用类型强调“值相等性”常用于DTO、配置项、领域对象。C# 9引入。record struct值类型的recordC# 10加入兼顾struct性能和值语义。写record的时候编译器会自动帮你生成相等性比较、ToString重写、解构方法这让很多样板代码直接消失。record Person(string Name, int Age); var p1 new Person(张三, 30); var p2 new Person(张三, 30); bool equal p1 p2; // true而不是比较引用初学者容易踩的坑是误以为record是“自动可变”的。实际上record默认是init-only也就是只能在初始化阶段赋值之后要改就得用with表达式生成副本。比如var p3 p1 with { Age 31 };。如果团队里有核心领域模型经常需要变化可以改用record class并在属性上声明set但这就失去了record的部分优势。我的经验是纯数据传输、无行为的模型优先用record需要依赖可变状态的场合老老实实用class小而不可变的几何/数学类型用struct或record struct。3.2 接口与抽象类不只是“都能被继承”这么简单接口Interface定义了一组能力契约抽象类Abstract Class则是一个“半成品”基类既能定义抽象成员也能提供已实现的方法、字段和构造逻辑。对比维度接口抽象类多继承一个类可实现多个接口一个类只能继承一个抽象类成员实现默认不含实现C# 8默认接口方法除外可包含抽象方法和普通方法字段不能包含实例字段可以包含字段构造器无构造器有构造器子类必须调用使用场景定义行为契约、依赖倒置抽取公共基类逻辑选接口还是抽象类我给团队的建议一直很朴素先考虑“这些类型之间是否有明确的‘是一种’关系”如果只是“都有某种能力”比如都能被序列化、都能运行、都能通知变化那就用接口如果有公共状态和算法的复用才考虑抽象类。近年来流行的“面向接口而非实现编程”实际上强调的是依赖关系上的抽象并不是鼓励把所有类都劈成接口实现类两件套。3.3 多态、虚方法、抽象方法、隐藏方法四种实现方式别混用多态Polymorphism是面向对象的招牌特性C#里实现多态的手段有虚方法virtual基类提供默认实现子类用override重写。抽象方法abstract基类只声明不实现子类必须override。隐藏方法new子类用new关键字重新定义一个同名方法但这不是真正的覆写编译期绑定看的是调用变量的类型。class Animal { public virtual string Speak() ……; } class Dog : Animal { public override string Speak() 汪汪; } class Cat : Animal { public new string Speak() 喵呜; } Animal dog new Dog(); Animal cat new Cat(); dog.Speak(); // 汪汪多态生效 cat.Speak(); // ……隐藏方法没有多态效果隐藏方法这个术语在面试和CR里经常被拿出来讨论因为很多开发者会以为new和override效果一样。实际区别是override改写的是方法表里的虚函数入口而new只是在子类里新增了一个同名方法如果通过基类引用调用永远走的是基类版本。我个人几乎不用方法隐藏因为它的语义容易引发混乱。碰上旧代码里有这种写法建议先评估能否改成override或改名方法。3.4 属性、自动属性、只读属性、计算属性字段的进阶形态属性Property是C#封装思想的重要工具它用getter和setter包装字段访问可以在读写时附加校验、日志、通知等逻辑。自动属性Auto-Property简化了无逻辑属性的写法public int Age { get; set; }由编译器生成字段。只读属性一般指只有get访问器的属性初始化后不可变。计算属性则是getter里进行计算没有专门的存储字段。public class Order { public decimal Amount { get; set; } public decimal TaxRate { get; init; } 0.06m; public decimal TotalAmount Amount * (1 TaxRate); public string StatusLabel { get { if (Amount 1000) return 大额订单; return 普通订单; } } }属性在序列化和ORM里也扮演重要角色很多框架默认只处理公开属性所以如果你把数据封装成了字段可能会发现序列化不出来。另外init访问器是C# 9起出现的“初始化专用”set它比set更严格不允许对象在构造完成后被随意改值这在不可变对象建模上很好用。理解属性本质上是方法这对术语才能解释为什么接口里能声明属性、基类虚属性可以被重写这类看似奇怪的问题。4. 现代C#语法糖与语言特性高频出现的进阶术语4.1 委托与事件别再傻傻分不清了委托Delegate本质是“方法的类型化引用”你可以把一个方法赋值给委托变量之后再调用就相当于间接调用了该方法。事件Event则是建立在委托之上的一种受限的发布-订阅模型它只能被外部“”和“-”不能像委托那样随意直接调用或者重新赋值。public delegate void NotifyHandler(string message); public class Publisher { public event NotifyHandler? Notify; // 外部只能 / -不能在类外面触发 Notify }这个限制的特点决定了事件适合当“广播通知”委托适合当“回调参数”。比如LINQ里的FuncT,bool就是一个委托实例你往Where里传lambda其实就是在传递一个回调方法。写代码时的一个体会如果某个方法参数只需要执行者的一个方法用委托如果是希望某个对象在特定时机通知大家用事件。把事件当委托来公开或者反过来都会留下维护隐患。4.2 Lambda与LINQ查询语法背后的大脑Lambda表达式是现代C#里最常见的函数式语法。它的核心是“把方法体当作表达式值来传递”。x x.Age 18这个写法在编译器眼里就是一个匿名函数。LINQLanguage Integrated Query是C#里专门用于数据查询的一整套操作符和语法。它有两种形态查询语法类似SQL的写法和方法语法链式调用Where、Select、GroupBy等。比如var adults people.Where(p p.Age 18) .OrderBy(p p.Name) .Select(p new { p.Name, p.Age });需要掌握的一个重要术语是“延迟执行”Deferred Execution大多数LINQ方法并不会在调用那一刻立即执行而是等到结果真正被枚举时才逐条计算。这带来一个经典坑——如果你在循环里一遍遍对同一个IEnumerable执行LINQ查询而底层数据源已经变化每次枚举的结果可能都不一样。解决方式很简单需要稳定快照时加.ToList()或.ToArray()立即物化。另一个区别是LINQ to Objects和LINQ to SQL或EF Core查询在语义上的差异前者直接操作内存对象后者会把表达式树翻译成SQL因此很多C#方法不能在数据库端执行选错会引发全表扫描这是性能优化的重点战场。4.3 泛型与集合类型类型安全的大杀器泛型Generic是在类或方法中延迟指定具体类型的一种机制。ListT、DictionaryTKey,TValue是典型代表。泛型的价值在于编译期确定类型避免装箱拆箱并且提供了统一的算法和数据结构模板。集合相关的常见术语还有IEnumerable 可被枚举的序列只读遍历是LINQ的基石。ICollection 、IList 提供数量、增删等更完整的集合语义。IReadOnlyList 只读列表适合防止集合被意外修改时返回给调用方。HashSet 基于哈希的无序唯一集合查重性能极高。Queue 、Stack 先进先出、后进先出的队列和栈。LinkedList 链表结构适合频繁插入删除的业务场景。我自己在项目里选集合类型的基本决策顺序是数据量小、只遍历用IEnumerable或数组需要下标随机访问用List需要按key高效查找用Dictionary需要保证唯一性且顺序不重要用HashSet。不要一上来就List一把梭很多问题其实源于结构选型不对。4.4 迭代器、yield return与异步迭代器迭代器Iterator是一个能按需逐个返回元素的方法最直观的体现就是yield return和yield break。带yield的方法会被编译器改造成一个状态机对象调用方每请求一个元素它就从一个暂停位置继续跑。public IEnumerableint GetNumbers() { yield return 1; yield return 2; yield return 3; }理解迭代器的好处是写出高效的分页、流式处理逻辑。比如读取一个大文件时不一次性全加载而是按行yield内存占用能降低好几个数量级。C# 8开始await foreach配合异步迭代器IAsyncEnumerableT可以流式消费异步产生的数据这在从数据库或网络接口分页获取大结果集时特别有用。有个细节迭代器方法里禁止使用ref和out参数一旦误用报错信息是CS1626等看到这个报错时第一反应就是检查是不是在yield方法里用了不安全参数。4.5 模式匹配让if/else变得面目全非的语法模式匹配Pattern Matching从C# 7开始逐步引入到C# 9、C# 10、C# 11后已经非常完整。常见形式包括类型模式x is string s、属性模式{ Length: 5 }、关系模式 0、逻辑模式is 1 and 10、列表模式[1, 2, .. rest]等。static string Describe(object obj) obj switch { int i when i 0 负数, int 0 零, int 0 正数, string { Length: 0 } 空字符串, string s $字符串:{s}, _ 其他 };模式匹配并不是花架子。它能让判断逻辑扁平化减少嵌套的if-else和强转尤其在领域建模和策略分发场景中非常实用。我现在写类型分派逻辑时默认优先尝试用switch表达式配合模式匹配代码可读性比一大串if清楚得多。但值得注意的是模式匹配虽然表达力强过度变形也会让团队里的新手看不懂建议控制单个表达式的复杂度必要时拆成多个方法。5. 异步与并发术语多线程时代的必会词汇5.1 Task、async与await从回调地狱到同步写法Task表示一个异步操作它既可以代表一个即将完成的计算也支持等待完成、取消、组合多个操作。async/await则是建立在Task之上的语法糖让异步代码写起来像同步代码。public async Taskstring FetchDataAsync() { using var http new HttpClient(); string content await http.GetStringAsync(...); return content; }这里要澄清一个常见误解async方法并不等于把方法放到了新线程上执行。真正决定“代码在哪里跑”的是await的Task本身。比如await Task.Run(...)才会把工作交给线程池而很多文件读取的异步API实际上是在IO完成时通过回调来恢复执行不占用线程。理解这个术语组合的价值在于排查死锁问题如果你在UI线程上同步调用.Result或.Wait()去等一个已开始的任务而那个任务内部又尝试回到同步上下文去更新UI就会形成经典死锁。最佳实践是“全程async/await不要混用同步阻塞”。5.2 同步上下文与ConfigureAwait一个容易被忽略的危险角落同步上下文SynchronizationContext是.NET里控制异步回调“在哪个线程上继续执行”的抽象。WinForms和WPF里的UI线程上下文、ASP.NET Core里的请求上下文都属于它的具体实现。ConfigureAwait(false)是Task的一个配置方法它告诉编译器等待完成后不需要回到原来的同步上下文。在UI应用里如果await之后要改UI控件就必须回到UI线程这时默认行为反而是对的在类库、后台服务、中间件里await之后通常不依赖上下文用ConfigureAwait(false)可以降低线程切换和死锁风险。string text await http.GetStringAsync(url).ConfigureAwait(false); ProcessText(text); // 不关心是否回到原上下文对于大多数非UI层的库代码我会统一默认使用ConfigureAwait(false)这是个性价比很高的习惯。不过它也有代价调试时堆栈上下文会变淡而且如果调用方后续依赖线程本地存储ThreadLocal/AsyncLocal就要谨慎处理。另外有一个很隐蔽的坑如果代码里大量混用async和旧同步代码出现“程序偶尔假死”的现象时优先排查方向和ConfigureAwait以及同步上下文脱不开关系。5.3 线程、线程池、并发集合与锁机制线程Thread是操作系统调度的最小单位线程池ThreadPool是.NET维护的一组复用线程用于执行Task和短性命任务。大多数情况下普通开发者不需要手动创建Thread使用Task.Run或异步API就够了。并发编程中的常用术语还包括lockMonitor类语法糖保证临界区内代码在同一时刻只被一个线程执持离开。Mutex跨进程互斥体可用于多进程同步。Semaphore/SemaphoreSlim信号量限制同时访问某资源的线程上限。ConcurrentDictionaryTKey,TValue、ConcurrentQueue 线程安全的集合类。Interlocked对变量进行原子操作的静态类例如Interlocked.Increment(ref count)。我最想强调的一个点是锁不是银弹。过多的锁会引发锁竞争和死锁有的场景更适合用并发集合或者原子操作。“能用无锁数据结构解决的问题就不要引入锁”是我长期实践下来的感觉。如果真的需要设计多线程协作流程建议画一个时序或状态流转图把共享状态和锁粒度都写明或者在代码里写清楚注释。曾经接手过一个项目多个锁的获取顺序不一致最终在高峰期出现死锁排查了半个通宵才发现是把锁A套锁B、另一个方向却把锁B套锁A所以“锁顺序一致”是并发编码的黄金规则。5.4 并发、并行与异步三个术语到底差在哪这几个词在中文语境下经常混用但它们指代不同层次并发Concurrency系统能同时处理多个任务的属性强调结构上的交错执行。并行Parallelism同一时间真的有多个计算单元同时在执行依赖多核硬件。异步Asynchronous不阻塞当前调用线程去等待任务完成而是让出控制权后续通过回调或await恢复。换言之异步是实现并发的一种手段并行则是利用多核资源的运行模式。一个单核CPU也可以有并发通过时间片轮转但无法真正并行。C#里Parallel类如Parallel.For用来做并行循环Task可以表达并行操作async/await处理的是异步流。看到这里你应该能理解处理IO密集任务首选异步处理CPU密集型任务才考虑并行。6. .NET平台与运行时术语从源码到机器码的暗号6.1 CLR、托管堆、垃圾回收与JIT代码跑起来之前发生了什么CLRCommon Language Runtime是.NET程序运行的虚拟机核心负责加载程序集、管理内存、执行安全检查、以及把IL转成机器码。理解CLR的几个核心概念ILIntermediate LanguageC#编译器编译产出的中间语言。JITJust-In-Time编译运行时把IL转换成当前平台可执行的机器码。托管堆Managed Heap由GC管理的内存区域对象分配在这个堆上。垃圾回收GCCLR自动回收不再被引用的对象它分代Gen 0/1/2管理以空间换时间。用一张表来理解对象的生命周期阶段说明分配在托管堆上分配内存引用类型变量保存引用地址使用通过变量访问对象GC跟踪引用关系不可达对象不再被根引用根包括静态字段、局部变量等回收GC回收内存压缩托管堆减少碎片日常开发里我们很少直接和GC打交道但理解“托管堆”和“栈”的分配差异对调优很有用。比如在循环体里频繁创建大对象会导致Gen 2频繁回收、引发卡顿改用结构体、复用对象或者使用ArrayPoolT都会有改善。前端时间做一个高频消息处理服务就是靠减少短命对象分配和引入对象池把GC压力降了一半多。6.2 .NET Framework、.NET Core 与 .NET 8版本名词对照这个领域是很多新人最容易晕的地方。简单理一遍.NET Framework老牌Windows桌面/服务端框架仅限Windows已停止大版本迭代但存量项目很多。.NET Core跨平台重写版从1.0一路走到3.1可以认为是.NET 5的前身。.NET 5/6/7/8随.NET Core和Framework统一而来的“一个.NET”时代。.NET 8是长期支持LTS版本目前最稳的生产选择。.NET Standard一套 API 规范类库可以兼容多个.NET实现但现在普通项目直接用net8.0目标框架即可。如果你在接手遗留系统看到目标框架写的是net472说明是.NET Framework新项目一律推荐.NET 8。这个选择背后的理由是跨平台、性能更好、新语言特性支持最全、社区资料都以它为准。选型时别看热闹要看交付团队对哪个生态熟悉。6.3 程序集、命名空间与NuGet组织与复用代码的关键词程序集Assembly是.NET里可部署和加载的最小单元一般就是编译出来的.dll或.exe包含IL代码、元数据、资源文件。命名空间Namespace是类型组织的逻辑分组解决同名冲突。NuGet是.NET生态的包管理器它的包可以是一个或多个程序集加元数据的压缩文件。项目里的PackageReference节点声明依赖恢复后会下载对应的库。日常开发中顶层语句、全局using、隐式using都是从C# 9/10开始提高代码整洁度的语法特性。global using可以让你在全局定义常引用的命名空间不用每个文件都写。ImplicitUsingsenable/ImplicitUsings是SDK项目模板默认开启的它会自动引用一批基础命名空间。理解程序集和命名空间不仅是为了组织代码更关系到依赖设计。好的分层系统各程序集之间是单向引用业务层依序依赖领域层表现层依赖应用层。一旦出现循环引用就先考虑是否该抽公共接口/抽象层。NuGet依赖管理上也有一条经验能少引包就少引别让“依赖地狱”成为项目隐患。6.4 反射、特性与表达式树元数据一词撑起的半壁江山反射Reflection是运行时检查和操作类型元数据的能力通过typeof、Type.GetType()、Assembly.GetTypes()等手段获取类型信息再动态创建实例、调用方法。特性Attribute是挂在类型/方法/属性上的元数据标签比如[Obsolete]、[Serializable]、ASP.NET Core里的[HttpGet]等都属于它。表达式树Expression Tree则是把lambda表达式表示为数据结构而不是编译成委托目的是让代码能在运行时被解析、改写、翻译。ExpressionFuncint, int expr x x * 2; // 这个表达式可以被 EF Core 翻译成 SQL齐这一个场景你用EF Core查询数据库Where(u u.Age 18)这个lambda之所以能被转成SQL就是因为框架拿到的是表达式树而不是一个已经编译好的委托。所以对ORM来说能不能“看懂”你的lambda是关键。这也解释了为什么日志里经常出现“The LINQ expression could not be translated”——说明你写的某个方法不能转换成SQL。理解反射、特性、表达式树三者之后不管是用内置框架还是自己设计一个小型插件系统思路都会清晰很多。7. C#各版本新增特性速查表很多人在项目里看同事代码发现某些语法不认识回头一查才发现是这个版本的新特性。整理一张速查表很有价值它方便你在不同代码仓库里快速定位“这个写法是哪个版本引入的”。C#版本核心新特性简介C# 2.0泛型、可空值类型、迭代器、匿名方法C# 3.0LINQ、Lambda、自动属性、匿名类型、扩展方法C# 4.0dynamic、命名参数和可选参数、协变/逆变C# 5.0async/await、调用方信息特性C# 6.0字符串插值、null条件操作符、表达式属性、using staticC# 7.0out变量、模式匹配、元组、本地函数、ref返回C# 8.0可空引用类型、异步流、接口默认方法、switch表达式C# 9.0record、init访问器、顶层语句、模式匹配增强C# 10.0全局using、文件作用域命名空间、record struct、扩展属性模式C# 11.0原始字符串、泛型数学、required成员、列表模式、UTF-8字符串字面量C# 12.0主构造函数、集合表达式、ref readonly参数、内联数组以C# 12为例主构造函数让简单数据类的定义变得更紧凑public class Point(double x, double y) { public double X { get; } x; public double Y { get; } y; }看这个表很容易发现语言演进的大趋势让代码更简洁、更安全、更注重数据表达。如果你的项目停留在老版本framework且没升级C#编译器就会和不少现代特性无缘。我的建议是不用追求把所有最新语法都强行用上团队统一约定一个C#版本区间新代码优先使用稳定且被团队成员熟知的特性。8. 实际使用这套术语表的经验与建议8.1 建立团队的术语库我最初整理C#术语表是因为项目里总出现“每个人说的名词不一样”的情况。有人说“事件订阅”有人说“注册回调”还有人直接说“绑事件”——其实意思一样但表达不一致会干扰沟通。后来我把高频术语整理成一个在线文档每次Code Review时碰到新词就补充慢慢形成了一套团队专用词汇表。效果是新人入组时的学习成本降低了跨组沟通时也和更准确。如果你也想做这件事我建议按如下步骤操作先按类别列出当前项目最常用的50到100个术语不需要贪多。每个术语写三行一句话解释、典型代码示例、常见坑。在团队Wiki里建一个“C#术语”页面遇到新人提问就把链接发过去。每隔两三个月回看一次表把过时或已废弃的术语标注出来。8.2 不要为了术语而术语工作中我见过有人满口“闭包”“柯里化”“表达式树”“依赖倒置”但一写代码就崩塌这其实是本末倒置了。术语是思维的工具不是装饰品。真正懂术语的人是在写代码和下决策时能自然地说出“这里用event不合适直接用委托回调更简单”或者“这段逻辑可以考虑用模式匹配重写比三个if嵌套清晰”而不是在聊天里疯狂堆名词。所以读这篇文章我的建议是不要通篇背诵而是挑出你实际工作中最常遇到的术语结合项目代码去反推和理解。比如下次看到IEnumerableT就想想它和ListT在延迟执行、性能、可变性上的区别下次收到TLS相关报错再去把类、接口、委托的关系彻底搞清楚。这张表是一个索引真正重要的是索引背后的代码世界。许多年后当我回看这个行业最让我感慨的仍然是新技术层出不穷但有些基础术语经得起时间考验。越早把这些概念搭建好后面学什么新框架都更快。这套术语表到现在已经陪我梳理了好几轮每一次整理都有新的理解。希望这份梳理也能成为你案头不断迭代的一份参考资料。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑