C#从现象到本质
书籍作者:郝亦非 |
ISBN:9787111604402 |
书籍语言:简体中文 |
连载状态:全集 |
电子书格式:pdf,txt,epub,mobi,azw3 |
下载次数:5031 |
创建日期:2021-02-14 |
发布日期:2021-02-14 |
运行环境:PC/Windows/Linux/Mac/IOS/iPhone/iPad/Kindle/Android/安卓/平板 |
内容简介
本书详细介绍用C#语言进行程序开发需要掌握的知识和技术。全书由浅入深分三大部分,共21章,部分“基础知识”,包括.NET基础知识、C#类型基础、C#的面向对象技术、字符串、垃圾回收、异常处理;第二部分“C#特性”,包括委托和事件、泛型、反射、数据结构、LINQ的相关技术、动态语言运行时;第三部分“多线程和异步”,包括多线程的概念、多线程同步、异步编程理论与实例、任务并行库等。本书精选大量案例,循序渐进地讲解C#语言,内容丰富而翔实,并给出练习题,帮助读者更好地巩固所学知识,提升能力。前言和附录分别给出.NET程序员开发职位要求、技能等级、进阶之路,以及面试宝典,可帮助开发者新人快速进阶,找到适合自己的工作。
作者简介
郝亦非 .NET开发人员,拥有多年开发经验,长期负责后端系统的搭建、重构与维护,对C#语言理解深刻,在工作中积累了丰富的开发经验,乐于分享,在社区贡献了大量文章。
编辑推荐
适读人群 :1.所有软件开发人员。2.高校相关专业的师生。
一个称职的.NET开发人员应该具备哪些C#技能?如何快速提升C#编程技巧?本书给出了非常详细的解读,主要内容包括C#基本概念,如字符串、圾回收、异常处理等,C#编程技巧,如委托和事件、泛型、反射、数据结构、LINQ、动态语言运行时等,还介绍了一些C#进阶内容,如多线程同步、异步编、任务并行库等。本书精选大量案例,内容丰富而翔实,还介绍了.NET程序员开发职位要求、技能等级、进阶之路,以及面试要点,可帮助开发者快速进阶,找到适合自己的工作。
前言
Introduction?引 言各位读者,大家好!或许你现在还是一名在校大学生,立志在毕业之后找一份程序员的工作,开始自己的职业生涯;或许你已经在一家公司“搬砖”,过着稳定的打工生活;或许你是一名创业者,时不时还要写点代码;或许,你只是对.NET平台和C#语言软件开发有浓厚的兴趣。总之,你一定是对自己现在掌握的C#知识还不满意,希望更上一层楼。如果是这样的话,本书就是为你而写的。本书不适合完全不了解C#的人士阅读,所以我假定你至少有一点C#的开发经验,懂得C#的基本语法。
那么一个合格的.NET程序开发人员,需要掌握哪些知识?这些知识应该如何去准备?如果把.NET程序开发人员简单地分为初级、中级和高级的话,自己又应当属于哪一级呢?下面先从.NET程序开发职位要求讲起。
.NET程序开发职位要求曾几何时,面向对象编程语言是Java一统天下,但现在,.NET开发的职位越来越多,很多大型企业也选择.NET平台搭建自己的系统与服务,在各大招聘网站上都活跃着大量的.NET开发职位,这些职位的技能要求互不相同,但可以简略归纳为三部分:
必要技能:包括主语言相关、设计与架构相关、岗位相关、数据库相关、线程相关以及语言相关。
加分技能:包括软件工程相关以及其他。
软性技能:包括文档书写、分析问题与解决问题的能力、沟通能力等。
例如,图1为某招聘网站上的一个“.NET资深开发工程师”的岗位要求。其中第1~5条都属于必要技能,包括对.NET平台开发经验的年限要求,以及掌握ASP.NET. MVC、WebAPI等各类.NET平台部件的要求。第4条为设计与架构相关要求,第5条则是数据库方面的要求。第6~7条为软性技能,第8~9条为加分技能(通常有“优先”等字)。
那么,知道了应聘的要求,我们该如何进行准备呢?针对每种不同要求,又需要如何学习?下面主要讨论必要技能和加分技能。
必要技能虽然各个岗位对必要技能的要求不同,但一般来说,必要技能可以划分为几部分,如图2所示。本书重点讨论C#相关和线程这两部分,对设计与架构涉及较少。岗位相关、数据库和语言技能则不在本书的讨论范围之内。
C#相关由于本书主要讨论.NET和C#,所以我就默认C#是岗位要求的主语言。对于.NET程序开发人员来说,主语言包括C#本身,以及它的运行环境.NET开发平台。对于C#语言来说,我认为十分重要,必须要掌握的知识点如下(参见图3):
.NET平台基础知识,包括.NET平台构成,.NET平台语言的编译(IL和JIT),以及编译之后的结果—程序集的结构和部署。另外,什么时候需要直接操作程序集(反射),及其优缺点。
C#类型基础。C#包括引用类型和值类型,及其区别和联系,它们在内存上又是如何分配的。
C#作为面向对象的语言,是怎样体现了面向对象的三大特征:封装、继承和多态的,接口、抽象类的区别和联系,以及何时考虑使用接口。
内存管理和垃圾回收机制是什么样的;根据CLR的垃圾回收机制,我们又应当做些什么。
C#中主要的数据结构的区别和联系。C#提供了非泛型和泛型的集合,在什么情况下,选用什么数据结构,Array、ArrayList和List的区别和联系,字典的实现原理,不同数据结构查找和插入/删除的时间复杂度等。
C#每一代的主要特性:1)委托与事件、反射;2)泛型;3)LINQ;4)动态语言运行时;5)async/await归到异步部分(暂时不在这里提及)。其中,又以LINQ尤为复杂,它包括了扩展类型、Lambda表达式(表达式又是一个很大的话题)、闭包等,这些都是面试时常见的问题。对于这些形形色色的特性,除了可以答出它们的定义之外,还需要知道,为什么要引入它们,引入它们是为了解决什么问题,在没有它们的时候,同样的问题又是怎样解决的。
图3 .NET程序开发必要技能地图—C#相关对于上面这些问题,本书会一一进行讨论。上面这些知识点的掌握,是在简历上写下“熟悉C#”(注意,这里我没有使用“精通”二字)的前提。这部分知识也是面试时的重中之重,面试官筛人的利器。如果这些知识都不是很清楚,那么“熟悉C#”也就成了一句笑话。
设计与架构相关设计与架构相关的内容如图4所示,其重要性仅次于主语言,因为这个技能严重影响代码质量。这块内容的学习和理解绝非一日之功,对它进行“临时抱佛脚”基本是不可能的,通过考察面试者对设计模式、面向对象的理解,基本可以准确地将面试者归到高手、中等和初学者这三类中。当然,如果岗位本身比较初级,那么这方面的要求将会相应降低。
因为C#是一个面向对象的编程语言,所以,面向对象成为面试考察的重点内容。经典的设计模式就是灵活运用面向对象的结果。常用的知识点包括:
面向对象设计五大原则。光背书没用,一定要用过(在项目中用或者自己用)才能有自己的心得体会。
常用设计模式,包括单例模式、策略模式、观察者模式、工厂方法模式等,及其UML类图。
依赖注入的概念,以及依赖注入的工具。
对所有设计模式的全面讨论超出了本书的范围。本书第4章“C#和面向对象”会简单介绍面向对象设计五大原则。另外,本书会在讲述C#语言特性时穿插一些常用设计模式,例如事件和观察者模式、开闭原则和工厂方法模式等。
对设计模式的学习,可以参考著名的《设计模式:可复用面向对象软件的基础》这本书,它是设计模式的开山之作。另外,程杰的《大话设计模式》这本书,也以生动有趣的方式讲述了各种设计模式的原理和用法。然而,最重要的还是自己亲自操作实践,以写代码的方式体会设计模式的好处。
岗位相关如果用人单位招的是ASP.NET程序员,那么肯定得了解ASP.NET生命周期、路由、前后端传值、MVC,以及至少一门前端语言等。如果招的是后端,可能会问一些关于Web服务、WebAPI的知识。专门负责写WPF应用的岗位,可能会在线程上大做文章。这些知识都是.NET框架类库的一部分。本书不会讨论具体某个框架类库的使用,.NET平台各大主流框架类库都有众多相关书籍供参考。
当然,框架类库的基础知识点也很重要。例如对WPF,如果你不知道如何禁止用户更改窗口的大小,那没什么关系,上网一查即可;但如果你不清楚长任务时如何保证界面良好的响应,工作线程如何更改UI线程控件的值,那么你编写出来的WPF应用一定会让用户怨声载道。
有些岗位还需要应聘者清楚分布式、脚本语言、Linux环境、缓存、消息队列、高级算法、大数据应用等相关知识。对这些知识的掌握和理解,一方面需要看书,另一方面也要结合相关项目经验。岗位相关的知识点五花八门,因岗而异。
数据库相关确实有一些开发者不需要和数据库打交道,不过,大部分岗位都要求对数据库操作有一定了解。数据库方面的技能如图5所示,如果一个岗位要求熟悉数据库,那么面试官期待的将是:
使用主语言访问数据库并熟练掌握增删改查操作。对于C#做主语言的情况,可以使用非ORM(ADO.NET)或ORM(Entity Framework)两种工具。你了解你目前所使用的ORM吗?基本的SQL书写。DBMS常用对象及工具,例如表、视图、存储过程等。
数据库基础知识,例如什么是范式,为什么数据库要遵循范式,不遵循范式的数据库会产生什么问题,什么是索引(聚集索引和非聚集索引),索引的利弊等。
什么是事务,为什么需要事务,没有事务会怎么样,解释事务隔离层级。
上面说的都是关系型数据库中最重要的知识点,有些岗位还需要应聘者懂得非关系型数据库、数据仓库等。而至于数据库的一些其他知识,例如存储过程、触发器、性能优化等,限于篇幅,这里就不详细展开了,应聘者可以根据岗位需求自行准备。《数据库系统概念》是一本非常经典的大学教材及优秀参考书。
线程相关很多复杂的应用都会出现多线程的身影,线程相关的技能如图6所示。Windows操作系统赋予了我们使用线程的能力,我们可以利用多线程改善程序的性能。对这一块知识,很多初级开发者都不清楚,可能是由于没有机会写一个需要多线程的应用。关于多线程的材料较少,而且多为英文,也是初级开发者对于线程不清楚的另一个原因。
图6 .NET程序开发必要技能地图—线程相关但是,大型应用,或者对性能要求很高的应用,多线程则无处不在。.NET本身也提供了非常丰富的线程管理类库。本书第17~21章试图对这一块内容进行较为全面的讲解。
语言相关这里的语言相关是指使用英语的能力。具体来说,包括阅读英文文档、英文邮件写作,甚至使用英语和他人进行沟通的能力。对于外企来说,这块非常重要,而非外企则相对不那么重要,但由于目前大部分较为权威的文档和资料仍然是英文的,而且缺乏翻译,所以开发者还是需要把自己的英语水平提升,能够无障碍地阅读英文技术文档。
这一块的学习只能通过日积月累,别无捷径。不过,我不推荐大家马上拿来一本四六级甚至托福单词去背,因为,其中大部分单词在实际开发中都遇不到,而真正需要知道的单词(例如,delegate委托,interface接口等),要么不在词汇表里,要么根本不是这个意思,而你把abandon(四级的第一个单词)背得再熟,平时也基本看不见它。更快捷的方法是阅读MSDN文档,并把不会的单词记录下来。
加分技能软件工程和项目经验相关虽然也有单枪匹马搞定项目的例子,但那通常出现在“远古时代”,现在的软件开发项目越来越复杂,常常需要多个人组成团队一起合作。团队会有专门的项目经理负责需求的整理(也可能没有,如开发者自己兼职项目经理),制定开发进度,开发者同心协力,从小目标开始,分而治之,最终完成项目。面试官(可能是开发者,可能是管理开发者的团队领导),不仅仅关心一个团队新人是否有能力完成领导交给他的任务,也会关心这个新人是否可以和现有人员通力合作。面试官可能会问以下问题,并根据你的回答默默思考你和新团队的契合程度:
项目经验。你之前做过什么,最得意的项目是什么,你在其中处于什么角色,解决了什么问题。
你之前的项目是瀑布开发模型还是敏捷,你更喜欢哪种,敏捷有什么优点和缺点。
你之前公司的代码是如何实现版本控制的。
你对单元测试有什么认识,是否写过单元测试代码。
如果面试者对这一块很不清楚,或者,面试者之前完全没有用过相关的工具(代码控制、测试等),面试官可能会担心
目录
Contents?目 录
引 言
第一部分 基础知识
第1章 .NET基础知识 2
1.1 .NET框架介绍 2
1.2 .NET框架发展史 3
1.3 .NET框架的主要成员 5
1.3.1 两步编译与跨平台 5
1.3.2 CLR 6
1.3.3 CLI 7
1.3.4 CTS和CLS 8
1.3.5 框架类库(FCL) 8
1.3.6 基础类库(BCL) 9
1.4 程序集 10
1.4.1 反向工程—使用ILSpy观察IL 10
1.4.2 程序集与托管模块 11
1.4.3 程序集的部署 18
1.5 .NET程序的编译:IL与JIT 20
1.5.1 什么是IL(CIL) 21
1.5.2 初识IL 21
1.5.3 System.Reflection.Emit 31
1.5.4 即时编译(JIT) 33
1.5.5 运行时的验证 34
1.5.6 Visual Studio的编译模式与本地代码的优化 34
1.5.7 托管代码与非托管代码的互操作性 35
1.6 CLR启动与Hello World的运行 36
1.7 本章小结 37
1.8 思考题 37
第2章 C#类型基础(上) 38
2.1 公共类型系统 38
2.2 堆与栈 40
2.2.1 堆 40
2.2.2 栈 41
2.3 引用类型的内存分配 42
2.3.1 字段的对齐 44
2.3.2 同步块索引 45
2.3.3 方法表指针和类型对象 45
2.3.4 静态字段和属性 46
2.4 使用WinDbg探查内存 46
2.4.1 WinDbg简易命令速查 47
2.4.2 使用WinDbg探查引用类型 47
2.4.3 引用类型的复制 52
2.5 值类型 53
2.5.1 基元类型 54
2.5.2 值类型的内存分配 54
2.5.3 值类型的构造函数 56
2.5.4 何时考虑使用值类型 57
2.5.5 值类型是密封的 58
2.5.6 值类型和引用类型的区别与联系 58
2.5.7 嵌套:值类型与引用类型 58
2.6 装箱和拆箱 59
2.6.1 装箱的过程 59
2.6.2 拆箱的过程 60
2.6.3 如何避免拆箱和装箱 60
2.7 本章小结 61
2.8 思考题 61
第3章 C#类型基础(下) 62
3.1 类型的非方法成员 62
3.1.1 常量 62
3.1.2 字段 63
3.1.3 无参属性 64
3.1.4 有参属性 66
3.1.5 属性的意义 67
3.2 类型的构造函数和析构函数 67
3.2.1 静态类 67
3.2.2 实例构造函数(引用类型) 68
3.2.3 实例构造函数(值类型) 69
3.2.4 静态构造函数 69
3.2.5 构造函数的执行顺序 70
3.2.6 析构函数 71
3.3 类型的普通方法成员 72
3.3.1 方法表 73
3.3.2 使用WinDbg探查方法表 73
3.3.3 方法槽表与方法描述表在JIT前后的变化 75
3.3.4 方法调用 77
3.3.5 方法参数的按值传递和按引用传递 80
3.4 类型转换 82
3.4.1 将一个对象转换为它的基类型 83
3.4.2 将一个对象转换为它的派生类型 84
3.4.3 基元类型的类型转换 84
3.4.4 自定义类型转换 84
3.5 System.Object类型的主要方法 85
3.6 本章小结 90
3.7 思考题 91
第4章 C#和面向对象 92
4.1 面向对象程序设计 92
4.2 继承 93
4.2.1 方法表与继承 94
4.2.2 再论Call与Callvirt 94
4.2.3 IL中修饰方法的关键字 95
4.2.4 方法的重载、重写和隐藏 96
4.2.5 值类型的方法调用 100
4.3 接口和多态 101
4.3.1 抽象类与Is A关系 102
4.3.2 接口与Has A关系 102
4.3.3 显式接口实现 103
4.3.4 显式接口实现与泛型接口 104
4.3.5 抽象类VS接口 105
4.3.6 接口不继承自Object 106
4.3.7 接口方法分派 106
4.4 面向对象编程五大原则(SOLID) 106
4.4.1 单一职责原则 107
4.4.2 开闭原则 107
4.4.3 里氏代换原则 111
4.4.4 接口隔离原则 111
4.4.5 依赖倒转原则 112
4.5 本章小结 112
4.6 思考题 113
第5章 字符串 114
5.1 字符 114
5.2 字符串的特性 115
5.2.1 字符串与普通的引用类型相比 116
5.2.2 IL中创建字符串 116
5.2.3 字符串的不变性 117
5.2.4 通过成员来证明不变性 118
5.2.5 为什么要这么设计 119
5.3 字符串驻留 119
5.4 字符串的相加 121
5.5 不变性只是针对托管代码 124
5.6 本章小结 125
5.7 思考题 125
第6章 垃圾回收 126
6.1 垃圾回收的概念 127
6.1.1 GC堆的构造 127
6.1.2 识别垃圾 128
6.1.3 压缩 136
6.1.4 C#的GC规则总结 136
6.2 垃圾回收策略 136
6.2.1 Dispose方法和IDisposible接口 136
6.2.2 析构函数(终结器) 137
6.2.3 如何回收托管资源 140
6.2.4 如何回收非托管资源 142
6.2.5 using关键字 143
6.2.6 总结:怎样实现垃圾回收策略 144
6.3 GC的工作模式 145
6.3.1 工作站模式 145
6.3.2 服务器模式 146
6.4 大对象 146
6.5 本章小结 147
6.6 思考题 147
第7章 异常与异常处理 148
7.1 C#的异常处理 149
7.1.1 try 149
7.1.2 catch 149
7.1.3 finally 150
7.1.4 结构化异常处理 152
7.1.5 throw和throw ex 153
7.2 IL中的异常处理机制 155
7.3 开发中的异常处理 159
7.3.1 提高程序的健壮性 159
7.3.2 使用.NET自带的日志类型 159
7.4 本章小结 163
7.5 思考题 163
第二部分 C#特性
第8章 委托和事件 166
8.1 委托 166