Effective C#:改善C#代码的50个有效方法(原书第3版)
更新日期:2024-07-13 00:59:56
出版时间:2018-05
浏览量:1096
价格:0.0¥

书籍下载

内容介绍

内容简介

本书分为5个章节,第1章介绍一些常见的语言结构,它们是开发者手头必备的工具,无论创建什么样的类型与算法,都离不开它们;第2章介绍一些设计习惯,告诉你应该怎样把代码写得与托管环境相协调;第3章讲解怎样用泛型取代System.Object以及强制类型转换,并讨论一些高级技术,如约束、泛型特化、方法约束以及向后兼容等;第4章讲解LINQ、查询语法以及与之相关的语言特性,包括什么时候运用扩展方法把协定与实现相分离、怎样有效地使用闭包以及如何编写匿名类型等;第5章指引你把C#程序中的异常与错误处理好。

目录

本书赞誉
译者序
前言
第1章 C#语言的编程习惯1
第1条:优先使用隐式类型的局部变量1
第2条:考虑用readonly代替const8
第3条:优先考虑is或as运算符,尽量少用强制类型转换12
第4条:用内插字符串取代string.Format()20
第5条:用FormattableString取代专门为特定区域而写的字符串24
第6条:不要用表示符号名称的硬字符串来调用 API26
第7条:用委托表示回调28
第8条:用null条件运算符调用事件处理程序31
第9条:尽量避免装箱与取消装箱这两种操作34
第10条:只有在应对新版基类与现有子类之间的冲突时才应该使用 new修饰符38
第2章 .NET的资源管理42
第11条:理解并善用 .NET的资源管理机制42
第12条:声明字段时,尽量直接为其设定初始值47
第13条:用适当的方式初始化类中的静态成员50
第14条:尽量删减重复的初始化逻辑52
第15条:不要创建无谓的对象60
第16条:绝对不要在构造函数里面调用虚函数64
第17条:实现标准的dispose 模式67
第3章 合理地运用泛型74
第18条:只定义刚好够用的约束条件76
第19条:通过运行期类型检查实现特定的泛型算法82
第20条:通过IComparable及IComparer定义顺序关系88
第21条:创建泛型类时,总是应该给实现了IDisposable的类型参数提供支持95
第22条:考虑支持泛型协变与逆变98
第23条:用委托要求类型参数必须
提供某种方法104
第24条:如果有泛型方法,就不要
再创建针对基类或接口的
重载版本110
第25条:如果不需要把类型参数所
表示的对象设为实例字段,
那么应该优先考虑创建泛
型方法,而不是泛型类114
第26条:实现泛型接口的同时,还
应该实现非泛型接口118
第27条:只把必备的契约定义在接
口中,把其他功能留给扩
展方法去实现124
第28条:考虑通过扩展方法增强已
构造类型的功能128
第4章 合理地运用LINQ131
第29条:优先考虑提供迭代器方法,
而不要返回集合131
第30条:优先考虑通过查询语句来
编写代码,而不要使用循环
语句137
第31条:把针对序列的API设计得
更加易于拼接142
第32条:将迭代逻辑与操作、谓词
及函数解耦149
第33条:等真正用到序列中的元素
时再去生成153
第34条:考虑通过函数参数来放松
耦合关系155
第35条:绝对不要重载扩展方法162
第36条:理解查询表达式与方法调
用之间的映射关系165
第37条:尽量采用惰性求值的方式
来查询,而不要及早求值177
第38条:考虑用lambda表达式来
代替方法182
第39条:不要在Func与Action中
抛出异常186
第40条:掌握尽早执行与延迟执行
之间的区别188
第41条:不要把开销较大的资源捕
获到闭包中193
第42条:注意IEnumerable与
IQueryable形式的数据
源之间的区别206
第43条:用Single()及First()
来明确地验证你对查询结果
所做的假设211
第44条:不要修改绑定变量214
第5章 合理地运用异常220
第45条:考虑在方法约定遭到违背
时抛出异常220
第46条:利用using与try/finally
来清理资源224
第47条:专门针对应用程序创建异常231
第48条:优先考虑做出强异常保证237
第49条:考虑用异常筛选器来改写
先捕获异常再重新抛出的
逻辑244
第50条:合理利用异常筛选器的副
作用来实现某些效果248
中英文词汇对照表252

精彩书摘

  《Effective C#:改善C#代码的50个有效方法(原书第3版)》:
  这段代码采用null条件运算符(也就是?.)安全地调用事件处理程序。该运算符首先判断其左侧的内容,如果发现这个值不是null,那就执行右侧的内容。反之,若为null,则跳过该语句,直接执行下一条语句。
  从语义上来看,这与早前的if结构类似,但区别在于?.运算符左侧的内容只会计算一次。
  由于C#语言不允许?.运算符右侧直接出现一对括号,因此,必须用Invoke方法去触发事件。每定义一种委托或事件,编译器就会为此生成类型安全的Invoke()方法,这意味着,通过调用Invoke方法来触发事件,其效果与早前那种写法是完全相同的。这段代码可以安全地运行在多线程环境下,而且篇幅更为短小。因为只有一行代码,所以根本不用专门创建辅助方法,那样反而会扰乱类的设计。只用一行代码就能触发事件,这正是我们想要的效果。
  旧的习惯固然很难改掉,但对于写了很多年.NET程序的人来说,还是应该努力培养新的习惯才对。早前那种写法可能已经用在你们公司目前的代码中了,要想把那些地方改成新的写法,开发团队可能要做出很大的转变。如果你在触发事件的时候头一次碰到NullReferenceException问题,然后上网求助,那么会搜索到很多推荐旧式写法的文章,那些经验是根据十几年前的情况而总结的。
  有了这种简单而清晰的新写法之后,原来的老习惯就需要改一改了。以后在触发事件的时候,都应该采用这种写法。
  ……

前言/序言

Preface 前  言
本书第1版于2004年出版,到了2016年,C#开发社群的情况已经有了很大的变化。使用这门语言编写程序的人越来越多,很多人现在都把C#当作首选的工作语言,并且不会再按照使用其他语言时所形成的那些习惯来使用这门语言。此外,C# 开发者所具备的经验各不相同,从刚毕业的学生到拥有数十年经验的专业开发者,都有人在用C#写程序,而且 C# 所支持的平台也比原来更加广泛。你可以用它架设服务器或制作网站,也可以为各种操作系统开发桌面版本或移动版本的应用程序。
这次升级的第3版既考虑到C#语言本身的变化,也考虑到使用这门语言的人(或者说 C# 开发社群)所发生的变化。笔者并不打算讲述C#语言的演变历程,而是关注怎样用好当前版本的 C# 语言。旧版的某些条目已经与当今的 C# 语言或 C# 应用程序脱节了,这些内容不会出现在新版中。新版中会添加一些条目,以讲述 C# 语言的新特性与 .NET 框架的新功能,这些内容是从软件产品的开发过程中提炼出来的,许多C#开发者采用这些特性开发了多个版本的软件。看过《More Effective C#》第1版的读者稍后可能会发现,那本书里的某些内容已经移到了本书中。在本书第3版中,笔者重新编排《More Effective C#》的内容,删除了原有的许多条目,以便在那本书的第2版中添加其他一些条目。总之,这本书里的 50 个条目都是一些编程建议,可以帮助你更为高效地使用 C# 语言,从而成为更加专业的开发者。
本书预设的语境是 6.0 版本的 C#,然而笔者并不会把该版本的功能全都拿出来讲。与Effective Software Development系列的其他书一样,这本书所关注的也是怎样用语言特性来解决日常工作中可能遇到的问题,并提供实用的建议。在 C# 6.0 版的这些特性中,笔者会特意挑出一些来讲,因为其中的某些特性能够使开发者以更好的方式来编写常用的代码。网上搜到的写法可能是针对许多年前的C#版本而写的,有了新版C#所引入的特性之后,开发者就可以用更好的写法来完成那些任务了,对于此类情况,笔者会专门指出。
书中的很多建议都可以用Roslyn平台的Analyzer及Code Fix加以体现,从而验证开发者所写的代码是否符合这些建议。笔者把相关的Analyzer放在了这里:https://github.com/BillWagner/EffectiveCSharpAnalyzers。你可以提交 issue,以表达自己的看法,或是发送 pull request为项目添加新的内容。
读者对象本书面向的是那些使用 C# 来完成日常工作的职业开发者。由于本书假设读者已经熟悉了 C# 的语法及语言特性,因此,并不会按部就班地讲解这些特性,而是会告诉你应该怎样把当前这一版 C# 语言所拥有的各种特性融入日常的开发工作中。
除了要熟悉语言本身的特性之外,还应该对 CLR(Common Language Runtime,公共语言运行时)及 JIT(Just-In-Time,即时)编译器有所了解。
内容提要有一些语言结构是每次写 C# 程序时几乎都会用到的,这些常见的写法出现在本书的第1章中,它们是开发者手头必备的工具,无论创建什么样的类型与算法,都离不开这些工具。
尽管 C# 程序运行在托管环境中,但并不是说开发者什么事情都不用操心。要想令程序的性能满足需求,就必须编写出能够与托管环境相协调的代码,这不是单靠性能测试与性能调整就可以实现的。因此,第2章会介绍一些设计习惯,告诉你应该怎样把代码写得与托管环境相协调。以良好的设计风格为基础,可以更加有效地优化细节问题。
自C# 2.0以来所引入的很多新技术都是以泛型为依托的。第3章讲解怎样用泛型取代System.Object以及强制类型转换,然后,笔者会讨论一些高级技术,例如约束、泛型特化、方法约束以及向后兼容等。读完本章之后,你会学到很多泛型技巧,从而能够更加顺畅地表达出自己的设计思路。
第4章会讲解 LINQ、查询语法以及与之相关的语言特性。你会了解到在哪些情况下应该运用扩展方法把协定与实现相分离,还会学到应该怎样有效地使用闭包以及如何编写匿名类型。此外,笔者还会解释编译器怎样把查询关键字映射成方法调用、如何区分委托与表达式树以及必要时怎样在二者之间转换,以及如何对查询做出转义以获取纯量形式的结果。
第 5 章会指引你把 C# 程序中的异常与错误处理好。笔者要讲解怎样确保程序中的错误能够得到适当的汇报,以及如何令程序的状态在出错之后依然保持稳定,甚至与出错之前一样。此外,你还会学到怎样给使用代码的人提供便利,令他们能够更加顺畅地调试你所编写的程序。
代码约定要想把范例代码印在书中,就必须在保持清晰的前提下顾及篇幅。笔者尽量把代码写得简短,以凸显其中最关键的部分,并把类或方法中的其他部分省掉。有时为了节省篇幅,还会把错误恢复代码也省掉。public 方法自然应该验证其参数以及外界输入给它的数据,但考虑到篇幅,笔者通常会把这些代码去掉。此外,很多复杂的算法还会对方法调用做出核查,而且会包含try/finally子句,这些代码也因同样的理由而删去。
常见的命名空间就不再写出了。你可以认为每一份范例代码前面都写有下面几条 using语句:
提供反馈意见笔者与本书的审阅者都尽力确保书中的内容正确无误,尽管如此,本书与范例代码里面可能还是会有一些错误,读者如果发现某个地方写错了,请发邮件至bill@thebillwagner.com,或通过Twitter号码@billwagner联系我。勘误表将会发布至http://thebillwagner.com/Resources/Effectivecs。书中的很多条目是笔者在与其他C#开发者通过电子邮件及Twitter讨论之后写出的,读者若对这些编程建议有疑问或意见,也请联系笔者。更为一般的话题可参见笔者博客:http://thebillwagner.com/blog。
致谢我要感谢为本书做出贡献的诸多人士。很荣幸能在这些年里与大家一起使用 C# 语言。C# Insiders 邮件列表中的每位朋友(无论身处 Microsoft 公司之内或之外)都为本书提供了创意,并且愿意与我交流,使我能把这本书写得更好。
必须特别感谢下面这几位 C# 开发者:Jon Skeet、Dustin Campbell、Kevin Pilch-Bisson、Jared Parsons、Scott Allen 以及 Mads Torgersen。感谢你们与我沟通、向我提供意见,并将其转变为具体的成果。这一版的很多新想法都是根据诸位的意见而形成的。
这一版的技术评审团队同样很出色。Jason Bock、Mark Michaelis 与 Eric Lippert 仔细阅读了文稿与范例代码,以确保读者能拿到一本优质的书籍。他们的水平相当高,不仅全面而彻底地审阅了本书,而且还提供了一些建议,帮助我把其中的很多话题解释得更为清楚。
我与Addison-Wesley出版社的编辑团队合作得相当愉快。Trina Macdonald 是一位优秀的编辑,总能督促我把书写好。Mark Renfro 与 Olivia Basegio 是她的得力帮手,我依靠他们完成了很多工作,这本书的定稿能够达到现在这样的质量,与他们的努力有很大关系,从头到尾的每一页内容都是如此。Curt Johnson 致力于发售这本技术图书,无论是哪种格式都有他的一份心力在里面。
感谢Scott Meyers再度将本书收入 Effective 书系,他阅读了整部文稿,并提出了一些改进建议。Meyers 虽然不是做 C# 的,但却有着丰富的软件开发经验,能够把文稿中没有解释清楚的地方找出来,而且能指出其中有哪些技巧还不足以总结成心得推荐给大家使用。他的意见,给我带来了很大的帮助。
感谢家人留出时间,令我可以写完这本书。我花了很长时间撰写书稿并制作范例代码,妻子 Marlene 总是给予我支持。有她的鼓励,我才能把这本书和其他的书写好。