《深入CLR(第4版 中文限量版)》针对CLR和.NET Framework 4.5(及更高版本)进行深入、全面的探讨,并结合实例介绍了如何利用它们进行设计、开发和调试。全书分5部分共30章。第Ⅰ部分介绍CLR基础,第Ⅱ部分解释如何设计类型,第Ⅲ部分介绍基本类型,第Ⅳ部分以核心机制为主题展开介绍,第Ⅴ部分重点介绍线程处理。
通过本书的阅读,读者可以掌握CLR和.NET Framework的精髓,轻松、高效地创建高性能应用程序。
作者Jeffrey Richter,全球知名的.NET和Windows大师,经典畅销书《Windows核心编程》和《CLR》系列的作者,其著作曾因其专业性和影响力荣获中国书刊业发行协会全行业畅销书品种称号。
专业力作全新全面升级
名著名译再现经典魅力
基于.NET Framework 4.5和VC# 2012,适用于2022版
重点探讨Framework Class Library(FCL)的核心类型
深度剖析垃圾回收、异常、泛型和线程处理等核心概念
享有全球盛誉的编程专家Jeffrey Richter,微软.NET团队长达十几年的知名技术顾问,在本书中以简洁流畅的语言将其数十年的经验和心得娓娓道来,独到而深刻的见解,深思熟虑之后形成的洞见,这些都让人醍醐灌顶,为日后构建健壮、可靠和响应快的应用程序与组件奠定良好的基础。
1999年10月,微软的团队首次向我展示了他们的成果:.NET Framework、公共语言运行时(Common Language Runtime,CLR)和C#编程语言。看到眼前的一切,我惊呆了,顿时觉得写软件的方式要发生重大变化了。他们聘请我担任他们的顾问,我当即就同意了。刚开始,我以为.NET Framework是Win32 API和COM上的一个抽象层。但随着我投入越来越多的时间进行研究,深刻认识到它是一个更宏大的项目。在某种程度上,它是自己的操作系统。它有自己的内存管理器、自己的安全系统、自己的文件加载器、自己的错误处理机制、自己的应用程序隔离边界(AppDomain)、自己的线程处理模型等。本书着重于解释所有这些主题,帮助大家为这个平台高效地设计和实现应用程序与组件。
我动手写这本书是2012年10月,距离首次接触.NET Framework和C#编程语言正好13年。13年以来, 我以微软顾问的身份开发过各种应用程序,为.NET Framework本身也贡献良多。我作为Wintellect(http://Wintellect.com)的合伙人,也为大量客户提供服务,帮助他们设计、调试、优化软件以及解决使用.NET Framework时遇到的问题。正是因为这些资历,我才知道如何用.NET Framework进行高效编程。贯穿全书,你会看到我数十年积累下来的经验。
本书面向的读者
本书旨在解释如何为.NET Framework开发应用程序和可重用的类。具体而言,我要解释CLR的工作原理及其提供的功能,还要讨论框架类库(Framework Class Library,FCL)的各个部分。没有一本书能完整地解释FCL其中含有数以千计的类型,而且这个数字一直在以惊人的速度增长。所以,我准备将重点放在每个开发人员都需要注意的核心类型上。
本书围绕Microsoft Visual Studio 2012/2013,.NET Framework 4.5.x和C# 5.0展开。由于微软在发布这些技术的新版本时,会试图保持很大程度的向后兼容性,所以本书描述的许多内容也适合之前的版本。所有示例代码都用C#编程语言写成。但由于CLR可由许多编程语言使用,所以本书内容也适合非C#程序员。
我和我的编辑们进行了艰苦卓绝的工作,试图为大家提供最准确、最新、最深入、最容易阅读和理解、没有错误的信息。但是,即便有如此完美的团队协作,疏漏和错误也在所难免。如果你发现了本书的任何错误或者想提出一些建设性的意见,请发送邮件给本书中文版编辑coo@netease.com。
致谢
没有来自其他人的帮助和技术支持,我个人是不可能写好这本书的。尤其要感谢我的家人。写好一本书所投入的时间和精力无法衡量。我只知道,没有我的妻子克里斯汀和两个儿子艾登和格兰特的支持,我根本不可能完成这本书。多少次想花些时间一家人小聚,都因为本书的写作而放弃。现在,总算告一段落,我终于有时间做自己喜欢做的事情了。
本书的修订得到了一些高人的协助。.NET Framework团队的一些人(其中许多都是我的朋友)审阅了部分章节,我和他们进行了许多发人深省的对话。克里斯托弗·纳沙雷参与了我几本书的出版,在审阅本书并确保我能以最恰当的方式来表达的过程中,他表现出了非凡的才能。他对本书的品质有至关重要的影响。和往常一样,我和微软出版社的团队进行了令人愉快的合作。特别感谢本·瑞安(Ben Ryan)、德文·马斯格罗夫(Devon Musgrave)和卡罗尔·迪林汉姆(Carol Dillingham)。另外,感谢苏茜·卡尔(Susie Carr)和坎迪斯·辛克莱尔(Candace Sinclair)提供的编辑和制作支持。
勘误和支持
我们一直以最大的努力保证本书的准确性。英文版勘误或更改会添加到以下网页:
http://www.oreilly.com/catalog/errata.csp?isbn=0790145353665
http://go.microsoft.com/FWLink/?Linkid=266601
如果发现的错误在此处未列出,可通过同一个网页联系我们。
如需其他支持,请发送邮件联系我们:
mspinput@microsoft.com
注意,上述邮件地址不提供产品支持。
最后,本书简体中文版的勘误和资源下载可以访问译者的博客,当前中文版已综合了英文版到(2023年)为止所有的勘误:
https://bookzhou.com
杰弗瑞·李希特(Jeffrey Richter)
Wintellect联合创始人。目前为微软的软件架构师合伙人,他是公认的Windows和.NET大师,数十年来影响了数十万优秀的程序员,他是多部经典著作的缔造者。他崇尚大道至简,注重效率与实用性,尤其热爱化繁为简,去芜存菁。值得一提的是,他特别擅长授人以渔,能够以通俗易懂、条理清晰的方式将普通读者望而却步的关键概念讲得透彻,讲得精彩。
他出版过很多本Windows/.NET畅销书,担任过MSDN的特约编辑、Win32、.NET两个答疑专栏以及Concurrent Affairs(关于并发那些事儿)专栏的作者。他还在很多全球性商业研讨会上发表演讲。作为最懂Windows和.NET的人,他从1990年开始以顾问身份为微软提供服务,他写的代码先后被微软的很多产品采用。此外,他还为AT&T、IBM、英特尔、梦工厂、通用和惠普等提供过咨询服务。
他爱好广泛,拥有飞机驾照和直升机驾照,还是国际魔法师协会成员。他爱好音乐(尤其是20世纪70年代的爵士乐和前卫摇滚乐)、击鼓、火车模型和空手道。他还喜欢旅游和戏剧。他与家人居住在华盛顿州的柯克兰。
周靖
微软MVP(最有价值专家),技术型知名译者。涉猎广泛,具有深厚的技术功底和良好的文学素养。早期痴迷于硬件,曾多年担任《微型计算机》杂志特约作者。继而潜心钻研程序设计并积累了丰富的编程经验。翻译风格严谨、准确、朴实、流畅,深受读者好评。代表译著有《C 入门经典》(第10版)、《Windows核心编程》(第5版中文限量版)、《深入CLR》(第4版 中文限量版)、《Visual C#从入门到精通》(第10版)、《学习Python》(第6版)以及《学习C 20》(中文版)等。
近两年,对机器学习有浓厚的兴趣,翻译出版《机器学习与人工智能实战:基于业务场景的工程应用》之后,开始研究、训练和应用大语言模型。
第I部分CLR基础
第1章CLR的执行模型
第2章生成、打包、部署和管理应用程序及类型
第3章共享程序集和强命名程序集
第Ⅱ部分设计类型
第4章类型基础
第5章基元类型、引用类型和值类型
第6章类型和成员基础
第7章常量和字段
第8章方法
第9章参数
第10章属性
第11章事件
第12章泛型
第13章接口
第Ⅲ部分基本类型
第14章字符、字符串和文本处理
第15章枚举类型和位标志
第16章数组
第17章委托
第18章定制特性
第19章可空值类型
第Ⅳ部分核心机制
第20章异常和状态管理
第21章托管堆和垃圾回收
第22章CLR寄宿和AppDomain
第23章程序集加载和反射
第24章运行时序列化
第25章与WinRT组件互操作
第Ⅴ部分线程处理
第26章线程基础
第27章计算限制的异步操作
第28章I/O限制的异步操作
第29章基元线程同步构造
第30章混合线程同步构造
术语表
详细目录
第I部分CLR基础
第1章CLR的执行模型 003
1.1将源代码编译成托管模块 003
1.2将托管模块合并成程序集 007
1.3加载公共语言运行时(CLR) 008
1.4执行程序集的代码 011
1.4.1IL和验证 017
1.4.2不安全的代码 018
1.5本机代码生成器NGen.exe 020
1.6Framework类库简介 022
1.7通用类型系统 025
1.8公共语言规范 027
1.9与非托管代码的互操作性 031
第2章生成、打包、部署和管理应用程序及类型 033
2.1.NET Framework部署目标 034
2.2将类型生成到模块中 035
2.3元数据概述 038
2.4将模块合并成程序集 045
2.4.1使用Visual Studio IDE将程序集添加到项目中 052
2.4.2使用程序集链接器 053
2.4.3为程序集添加资源文件 054
2.5程序集版本资源信息 055
2.6语言文化 060
2.7简单应用程序部署(私有部署的程序集) 061
2.8简单管理控制(配置) 063
第3章共享程序集和强命名程序集 067
3.1两种程序集,两种部署 068
3.2为程序集分配强名称 069
3.3全局程序集缓存 074
3.4在生成的程序集中引用强命名程序集 076
3.5强命名程序集能防篡改 077
3.6延迟签名 078
3.7私有部署强命名程序集 081
3.8运行时如何解析类型引用 082
3.9高级管理控制(配置) 085
第Ⅱ部分设计类型
第4章类型基础 093
4.1所有类型都从System.Object派生 093
4.2类型转换 095
4.3命名空间和程序集 100
4.4在运行时的相互关系 104
第5章基元类型、引用类型和值类型 113
5.1编程语言的基元类型 113
5.2引用类型和值类型 121
5.3值类型的装箱和拆箱 127
5.3.1使用接口更改已装箱值类型中的字段(以及为何不该这样做) 139
5.3.2对象相等性和同一性 142
5.4对象哈希码 145
5.5dynamic基元类型 147
第6章类型和成员基础 155
6.1类型的各种成员 155
6.2类型的可见性 158
6.3成员的可访问性 160
6.4静态类 162
6.5分部类、结构和接口 163
6.6组件、多态和版本控制 164
6.6.1CLR如何调用虚方法、属性和事件 167
6.6.2合理使用类型的可见性和成员的可访问性 171
6.6.3对类型进行版本控制时的虚方法的处理 173
第7章常量和字段 179
7.1常量 179
7.2字段 181
第8章方法 185
8.1实例构造器和类(引用类型) 185
8.2实例构造器和结构(值类型) 189
8.3类型构造器 192
8.4操作符重载方法 196
8.5转换操作符方法 200
8.6扩展方法 204
8.6.1规则和指导原则 206
8.6.2用扩展方法扩展各种类型 207
8.6.3ExtensionAttribute类 209
8.7分部方法 210
第9章参数 215
9.1可选参数和命名参数 215
9.1.1规则和指导原则 217
9.1.2DefaultParameterValue特性和Optional特性 218
9.2隐式类型的局部变量 219
9.3以传引用的方式向方法传递参数 221
9.4向方法传递可变数量的参数 227
9.5参数和返回类型的设计规范 229
9.6常量性 231
第10章属性 233
10.1无参属性 233
10.1.1自动实现的属性 237
10.1.2合理定义属性 238
10.1.3对象和集合初始化器 241
10.1.4匿名类型 243
10.1.5System.Tuple类型 246
10.2有参属性 248
10.3调用属性访问器方法时的性能 253
10.4属性访问器的可访问性 254
10.5泛型属性访问器方法 254
第11章事件 255
11.1设计要公开事件的类型 257
11.1.1第一步:定义类型来容纳所有需要发送给事件通知接收者的附加信息 257
11.1.2第二步:定义事件成员 258
11.1.3第三步:定义负责引发事件的方法来通知事件的登记对象 259
11.1.4第四步:定义方法将输入转化为期望事件 262
11.2编译器如何实现事件 262
11.3设计侦听事件的类型 264
11.4显式实现事件 266
第12章泛型 271
12.1FCL中的泛型 276
12.2泛型基础结构 277
12.2.1开放类型和封闭类型 278
12.2.2泛型类型和继承 280
12.2.3泛型类型同一性 282
12.2.4代码爆炸 283
12.3泛型接口 284
12.4泛型委托 285
12.5委托和接口的逆变和协变泛型类型实参 286
12.6泛型方法 288
12.7泛型和其他成员 291
12.8可验证性和约束 291
12.8.1主要约束 294
12.8.2次要约束 295
12.8.3构造器约束 296
12.8.4其他可验证性问题 297
第13章接口 301
13.1类和接口继承 302
13.2定义接口 302
13.3继承接口 304
13.4关于调用接口方法的更多探讨 306
13.5隐式和显式接口方法实现(幕后机制) 308
13.6泛型接口 309
13.7泛型和接口约束 312
13.8实现多个具有相同方法名和签名的接口 313
13.9用显式接口方法实现来增强编译时类型安全性 314
13.10谨慎使用显式接口方法实现 316
13.11设计:基类还是接口 319
第Ⅲ部分基本类型
第14章字符、字符串和文本处理 323
14.1字符 323
14.2System.String类型 327
14.2.1构造字符串 327
14.2.2字符串是不可变的 329
14.2.3比较字符串 330
14.2.4字符串留用 337
14.2.5字符串池 340
14.2.6检查字符串中的字符和文本元素 340
14.2.7其他字符串操作 342
14.3高效率构造字符串 343
14.3.1构造StringBuilder对象 343
14.3.2StringBuilder的成员 344
14.4获取对象的字符串表示:ToString 347
14.4.1指定具体的格式和语言文化 347
14.4.2将多个对象格式化成一个字符串 352
14.4.3提供定制格式化器 353
14.5解析字符串来获取对象:Parse 356
14.6编码:字符和字节的相互转换 358
14.6.1字符和字节流的编码和解码 364
14.6.2Base-64字符串编码和解码 365
14.7安全字符串 366
第15章枚举类型和位标志 371
15.1枚举类型 371
15.2位标志 378
15.3向枚举类型添加方法 381
第16章数组 383
16.1初始化数组元素 386
16.2数组转型 388
16.3所有数组都隐式派生自System.Array 391
16.4所有数组都隐式实现IEnumerable、ICollection和IList 391
16.5数组的传递和返回 392
16.6创建下限非零的数组 393
16.7数组的内部工作原理 395
16.8不安全的数组访问和固定大小的数组 399
第17章委托 403
17.1初识委托 403
17.2用委托回调静态方法 406
17.3用委托回调实例方法 408
17.4委托揭秘 408
17.5用委托回调多个方法(委托链) 412
17.5.1C#语言对委托链的支持 417
17.5.2取得对委托链调用的更多控制 417
17.6委托定义不要太多(泛型委托) 420
17.7C#为委托提供的简化语法 421
17.7.1简化语法1:不需要构造委托对象 422
17.7.2简化语法2:不需要定义回调方法(lambda表达式) 422
17.7.3简化语法3:局部变量不需要手动包装到类中即可传给回调方法 426
17.8委托和反射 429
第18章定制特性 433
18.1使用定制特性 434
18.2定义自己的特性类 437
18.3特性构造器和字段/属性数据类型 441
18.4检测定制特性 442
18.5两个特性实例的相互匹配 447
18.6检测定制特性时不创建从Attribute派生的对象 450
18.7条件特性类 453
第19章可空值类型 455
19.1C#语言对可空值类型的支持 457
19.2C#语言的空接合操作符 460
19.3CLR对可空值类型的特殊支持 461
19.3.1可空值类型的装箱 462
19.3.2可空值类型的拆箱 462
19.3.3通过可空值类型调用GetType 463
19.3.4通过可空值类型调用接口方法 463
第Ⅳ部分核心机制
第20章异常和状态管理 467
20.1定义异常 468
20.2异常处理机制 469
20.2.1try块 470
20.2.2catch块 471
20.2.3finally块 473
20.3System.Exception类 476
20.4FCL定义的异常类 480
20.5抛出异常 484
20.6定义自己的异常类 485
20.7牺牲可靠性来换取开发效率 488
20.8设计规范和最佳实践 497
20.8.1善用finally块 497
20.8.2不要什么都捕捉 499
20.8.3得体地从异常中恢复 500
20.8.4发生不可恢复的异常时回滚部分完成的操作维持状态 501
20.8.5隐藏实现细节来维系协定 502
20.9未处理的异常 505
20.10对异常进行调试 509
20.11异常处理的性能问题 511
20.12约束执行区域(CER) 514
20.13代码协定 517
第21章托管堆和垃圾回收 525
21.1托管堆基础 525
21.1.1从托管堆分配资源 526
21.1.2垃圾回收算法 527
21.1.3垃圾回收和调试 530
21.2代:提升性能 533
21.2.1垃圾回收触发条件 538
21.2.2大对象 539
21.2.3垃圾回收模式 539
21.2.4强制垃圾回收 542
21.2.5监视应用程序的内存使用 544
21.3使用需要特殊清理的类型 545
21.3.1使用包装了本机资源的类型 552
21.3.2一个有趣的依赖性问题 557
21.3.3GC为本机资源提供的其他功能 558
21.3.4终结的内部工作原理 563
21.3.5手动监视和控制对象的生存期 565
第22章CLR寄宿和AppDomain 573
22.1CLR寄宿 574
22.2AppDomain 576
22.3卸载AppDomain 590
22.4监视AppDomain 592
22.5AppDomain FirstChance异常通知 594
22.6宿主如何使用AppDomain 594
22.6.1可执行应用程序 594
22.6.2Silverlight富Internet应用程序 595
22.6.3ASP.NET和XML Web服务应用程序 595
22.6.4SQL Server 596
22.6.5更多的用法只局限于想象力 596
22.7高级宿主控制 597
22.7.1使用托管代码管理CLR 597
22.7.2写健壮的宿主应用程序 598
22.7.3宿主如何拿回它的线程 599
第23章程序集加载和反射 603
23.1程序集加载 604
23.2使用反射构建动态可扩展应用程序 609
23.3反射的性能 610
23.3.1发现程序集中定义的类型 610
23.3.2类型对象的准确含义 611
23.3.3构建Exception派生类型的层次结构 613
23.3.4构造类型的实例 615
23.4设计支持加载项的应用程序 618
23.5使用反射发现类型的成员 620
23.5.1发现类型的成员 621
23.5.2调用类型的成员 625
23.5.3使用绑定句柄减少进程的内存消耗 631
第24章运行时序列化 635
24.1序列化/反序列化快速入门 637
24.2使类型可序列化 641
24.3控制序列化和反序列化 643
24.4格式化器如何序列化类型实例 647
24.5控制序列化/反序列化的数据 648
24.6流上下文 655
24.7类型序列化为不同类型,对象反序列化为不同对象 657
24.8序列化代理 660
24.9反序列化对象时重写程序集/类型 665
第25章与WinRT组件互操作 667
25.1CLR投射与WinRT组件类型系统规则 669
25.2框架投射 673
25.2.1从.NET代码中调用异步WinRT API 674
25.2.2WinRT流和.NET流之间的互操作 678
25.2.3在CLR和WinRT之间传输数据块 680
25.3用C#语言定义WinRT组件 683
第Ⅴ部分线程处理
第26章线程基础 693
26.1Windows为什么要支持线程 694
26.2线程开销 695
26.3停止疯狂 698
26.4CPU发展趋势 701
26.5CLR线程和Windows线程 702
26.6使用专用线程执行异步的计算限制操作 703
26.7使用线程的理由 705
26.8线程调度和优先级 707
26.9前台线程和后台线程 712
26.10深入学习 714
第27章计算限制的异步操作 715
27.1CLR线程池基础 716
27.2执行简单的计算限制操作 717
27.3执行上下文 718
27.4协作式取消和超时 720
27.5任务 725
27.5.1等待任务完成并获取结果 726
27.5.2取消任务 728
27.5.3任务完成时自动启动新任务 730
27.5.4任务可以启动子任务 732
27.5.5任务内部揭秘 733
27.5.6任务工厂 735
27.5.7任务调度器 737
27.6Parallel的静态方法For、ForEach和Invoke 739
27.7并行语言集成查询(PLINQ) 743
27.8执行定时计算限制操作 746
27.9线程池如何管理线程 750
27.9.1设置线程池限制 750
27.9.2如何管理工作者线程 751
第28章I/O限制的异步操作 753
28.1Windows如何执行I/O操作 754
28.2C#的异步函数 758
28.3编译器如何将异步函数转换成状态机 760
28.4异步函数扩展性 764
28.5异步函数和事件处理程序 768
28.6FCL的异步函数 768
28.7异步函数和异常处理 770
28.8异步函数的其他功能 771
28.9应用程序及其线程处理模型 774
28.10以异步方式实现服务器 777
28.11取消I/O操作 777
28.12有的I/O操作必须同步进行 779
28.13I/O请求优先级 780
第29章基元线程同步构造 783
29.1类库和线程安全 785
29.2基元用户模式和内核模式构造 786
29.3用户模式构造 788
29.3.1易变构造 789
29.3.2互锁构造 794
29.3.3实现简单的自旋锁 799
29.3.4Interlocked Anything模式 803
29.4内核模式构造 805
29.4.1Event构造 809
29.4.2Semaphore构造 811
29.4.3Mutex构造 812
第30章混合线程同步构造 815
30.1一个简单的混合锁 816
30.2自旋、线程所有权和递归 817
30.3FCL中的混合构造 820
30.3.1ManualResetEventSlim类和SemaphoreSlim类 820
30.3.2Monitor类和同步块 821
30.3.3ReaderWriterLockSlim类 826
30.3.4OneManyLock类 829
30.3.5CountdownEvent类 831
30.3.6Barrier类 831
30.3.7线程同步构造小结 832
30.4著名的双检锁技术 834
30.5条件变量模式 839
30.6异步的同步构造 841
30.7并发集合类 846
术语表 851