您好,欢迎来到聚文网。 登录 免费注册
MORE EFFECTIVE C#:改善C#代码的50个有效方法原书第2版)

MORE EFFECTIVE C#:改善C#代码的50个有效方法原书第2版)

  • 字数: 290
  • 装帧: 平装
  • 出版社: 机械工业出版社
  • 作者: [美] 比尔·瓦格纳(Bill Wagner)
  • 出版日期: 2019-03-01
  • 商品条码: 9787111620716
  • 版次: 1
  • 开本: 16开
  • 页数: 257
  • 出版年份: 2019
定价:¥79 销售价:登录后查看价格  ¥{{selectedSku?.salePrice}} 
库存: {{selectedSku?.stock}} 库存充足
{{item.title}}:
{{its.name}}
精选
内容简介
在本书中,世界的.NET专家Bill Wagner介绍了用于写出健壮且容易完成的C# 7.0代码的50条中阶至高阶技巧,反映了C#语言及其开发社区的发展,可帮助读者解决每日编程工作中可能遇到的问题。
作者简介
比尔?瓦格纳(Bill Wagner),世界知名的C#专家,也是ECMA C#标准委员会成员。他在Humanitarian Toolbox项目中担任主管,并荣获微软公司.NET MVP称号长达11年,很近开始在.NET Foundation AdvisoryCouncil任职。Wagner在工作中与各种规模的公司合作,帮助这些创业公司或企业改进软件开发流程,并培养软件开发团队。目前,他是微软.NET核心内容团队的员工,写过很多与C#语言及.NET框架有关的学习资料。他拥有伊利诺伊大学厄巴纳-尚佩恩分校计算机科学专业的学士学位。
目录
译者序前言章  处理各种类型的数据 / 1条:使用属性而不是可直接访问的数据成员 / 1第2条:尽量采用隐式属性来表示可变的数据 / 7第3条:尽量把值类型设计成不可变的类型 / 11第4条:注意值类型与引用类型之间的区别 / 16第5条:确保 0 可以当成值类型的有效状态使用 / 21第6条:确保属性能够像数据那样运用 / 25第7条:用元组来类型的作用范围 / 30第8条:在匿名类型中定义局部函数 / 35第9条:理解相等的不同概念及它们之间的关系 / 400条:留意GetHashCode()方法的使用陷阱 / 49第2章  API设计 / 571条:不要在API中提供转换运算符 / 572条:尽量用可选参数来取代方法重载 / 613条:尽量缩减类型的可见范围 / 654条:优先考虑定义并实现接口,而不是继承 / 695条:理解接口方法与虚方法之间的区别 / 776条:用Event模式来实现通知功能 / 827条:不要把类的内部对象通过引用返回给外界 / 878条:优先考虑重写相关的方法,而不是创建事件处理程序 / 919条:不要重载基类中定义的方法 / 94第20条:了解事件机制为何会提升对象在运行期的耦合程度 / 98第21条:不要把事件声明成virtual / 100第22条:尽量把重载方法创建得清晰、简洁而完备 / 106第23条:让 partial类的构造函数、mutator方法和事件处理程序调用适当的partial方法 / 112第24条:尽量不要实现ICloneable接口,以便留出更多的设计空间 / 117第25条:数组类型的参数应该用params加以修饰 / 122第26条:在迭代器与异步方法中定义局部函数,以便尽早地报错 / 126第3章  基于任务的异步编程 / 131第27条:使用异步方法执行异步工作 / 131第28条:不要编写返回值类型为void的异步方法 / 136第29条:不要把同步方法与异步方法组合起来使用 / 141第30条:使用异步方法以避免线程分配和上下文切换 / 146第31条:避免不必要的上下文编组 / 147第32条:通过Task对象来安排异步工作 / 151第33条:考虑实现任务取消协议 / 157第34条:缓存泛型异步方法的返回值 / 164第4章  并行处理 / 167第35条:了解PLINQ是怎样实现并行算法的 / 167第36条:编写并行算法时要考虑异常状况 / 179第37条:优先使用线程池而不是创建新的线程 / 185第38条:考虑使用BackgroundWorker在线程之间通信 / 190第39条:学会在XAML环境下执行跨线程调用 / 194第40条:首先考虑用lock()实现同步 / 202第41条:尽量缩减锁定范围 / 209第42条:不要在加了锁的区域内调用未知的方法 / 212第5章  动态编程 / 217第43条:了解动态编程的优点及缺点 / 217第44条:通过动态编程技术更好地运用泛型参数的运行期类型 / 226第45条:使用DynamicObject和IDynamicMetaObjectProvider实现数据驱动的动态类型 / 229第46条:学会正确使用Expression API / 240第47条:尽量减少公有API中的动态对象 / 246第6章  加入全球C#社区 / 253第48条:最流行的写法不一定最合适 / 253第49条:与大家一起制定规范并编写代码 / 255第50条:考虑用分析器自动检查代码质量 / 256中英文词汇对照表 / 258
摘要
    章处理各种类型的数据C#语言原本是设计给面向对象的开发者使用的,这种开发方式会把数据与功能合起来处理。在C#逐渐成熟的过程中,它又添加了一些新的编程范式,以便支持其他一些常用的开发方式。其中有一种开发方式强调把数据存储方法与数据操作方法分开,这种方式随着分布式系统而兴起,此类系统中的应用程序分成多个小的服务,每个服务只实现一项功能,或者只实现一组相互联系的功能。如果要把数据的存储与操作分开,那么开发者就得有一些新的编程技术可供使用,正是这些需求促使C#语言添加了与之相应的一些特性。本章会介绍怎样把数据本身与操纵或处理该数据的方法分开。此处所说的数据不一定都是对象,也有可能是函数或被动的数据容器。条:使用属性而不是可直接访问的数据成员属性一直是C#语言的特色,目前的属性机制比C#刚引入它的时候更为完备,这使得开发者能够通过属性实现很多功能,例如,可以给getter与setter设定不同的访问权限。与直接通过数据成员来编程的方式相比,自动属性可以省去大量的编程工作,而且开发者可以通过该机制轻松地定义出只读的属性。此外还可以结合以表达式为主体的(expression-bodied)写法将代码变得更紧凑。有了这些机制,就不应该继续在类型中创建公有(public)字段,也不应该继续手工编写get与set方法。属性既可以令调用者通过公有接口访问相关的数据成员,又可以确保这些成员得到面向对象式的封装。在C#语言中,属性这种元素可以像数据成员一样被访问,但它们其实是通过方法来实现的。类型中的某些成员很适合用数据来表示,如顾客的名字、点的(x, y)坐标以及上一年的收入等。如果用属性来实现这些成员,那么在调用你所创建的接口时,就可以像使用方法那样,通过这些属性直接访问数据字段。这些属性就像公有字段一样,可以轻松地访问。而另一方面,开发这些属性的人则可以在相关的方法中定义外界访问该属性时所产生的效果。.NET Framework 会做出这样一种预设:它认为开发者都是通过属性来表达公有数据成员的。这可以通过其中与数据绑定(data binding)有关的类而得到印证,因为这些类是通过属性而非公有数据字段来提供支持的。WPF(Windows Presentation Foundation)、Windows Forms 以及 Web Forms 在把对象中的数据与用户界面中的控件绑定时,都以相关的属性为依据。数据绑定机制会通过反射在类型中寻找与名称相符的属性:这段代码会把textBoxCity控件的Text属性与address对象的City属性绑定。假如你在address对象中用的是名为City的公有数据字段,而不是属性,那么这段代码将无法正常运作,因为Framework Class Library的设计者本来就没打算支持这种写法。直接使用公有数据成员是一种糟糕的编程方式,Framework Class Library 不为这种方式提供支持。这也是促使开发者改用属性来编程的原因之一。数据绑定机制只针对那些其元素需要显示在用户界面(UI)中的类,然而,属性的适用范围却不仅仅局限于此。在其他的类与结构中,也应该多使用属性,这样可以让你在发现新的需求时,更为方便地修改代码。比方说,如果你现在决定Customer类型中的 name(名字)数据不应出现空白值,那么只需修改Name属性的代码即可:假如当初没有通过公有属性来实现Name,而是采用了公有数据成员,那么现在就必须在代码库里找到设置过该成员的每行代码,并逐个修改,这会浪费很多时间。由于属性是通过方法实现的,因此,开发者很容易就能给它添加多线程支持。例如可以像下面这样实现get与set访问器,使外界对Name数据的访问得以同步(本书第39条会详细讲解这个问题):C#方法所具备的一些特性同样可以体现在属性身上,其中很明显的一条就是属性也可以声明为virtual:请注意,刚才那几个例子在涉及属性的地方用的都是隐式写法。还有一种常见的写法,是通过属性来包装某个backing store(后援字段)。采用隐式写法时,开发者不用自己在属性的 getter 与 setter 中编写验证逻辑。也就是说,我们在用属性来表示比较简单的字段时,无须通过大量的模板代码来构建这个属性,编译器会为我们自动创建私有字段(该字段通常称为后援字段,并实现get与set这两个访问器所需的简单逻辑。属性也可以是抽象的,从而成为接口定义的一部分,这种属性写起来与隐式属性相似。下面这段代码,就演示了怎样在泛型接口中定义属性。虽然与隐式属性的写法相似,但这种属性没有对应的实现物。定义该属性的接口只是要求实现本接口的类型都必须满足接口所订立的契约,也就是必须正确地提供Name及Value这两个属性。在 C# 语言中,属性是功能完备的“一等公民”,它可以视为对方法所做的扩充,用以访问或修改内部数据。凡是能在成员方法上执行的操作都可以在属性上执行。此外,由于属性不能传递给方法中用ref或out关键字所修饰的参数,因此与直接使用字段相比,它可以帮我们避开与此有关的一些严重问题。对于类型中的属性来说,它的访问器分成 getter(获取器)与 setter(设置器)这两个单独的方法,这使我们能够对二者施加不同的修饰符,以便分别控制外界对该属性的获取权与设置权。由于这两种权限可以分开调整,因此我们能够通过属性更为灵活地封装数据元素:属性不只适用于简单的数据字段。如果某个类型要在其接口中发布能够用索引来访问的内容,那么就可以创建索引器,这相当于带有参数的属性,或者说参数化的属性。下面这种写法很有用,用它创建出的属性能够返回序列中的某个元素:与只代表单个元素的属性相似,索引器在 C# 语言中也受到很多支持。由于它们是根据你所编写的方法来实现的,因此可以在索引器的逻辑代码中进行相关的验证或计算。索引器可以是virtual(虚拟)的,也可以是abstract(抽象)的,可以声明在接口中,也可以设为只读或可读可写。若参数是整数的一维索引器,则可以参与数据绑定;若参数不是整数的一维索引器,则可以用来定义映射关系:和C#中的数组类似,索引器也可以是多维的,而且对于每个维度使用的索引,其类型可以互不相同:注意,索引器一律要用 this 关键字来声明。由于 C# 不允许给索引器起名字,因此同一个类型中的索引器必须在参数列表上有所区别,否则就会产生歧义。对于属性所具备的功能,索引器几乎都有,如索引器可以声明成 virtual 或 abstract,也可以为 setter 与 getter 指定不同的访问权限。然而有一个地方例外,那就是索引器必须明确地实现出来,而不能像属性那样可以由系统默认实现。属性是个相当好的机制,而且它在当前的 C# 语言中所受的支持比在旧版 C# 语言中更多。尽管如此,有些人还是想先创建普通的数据成员,然后在确实有必要的情况下再将其替换成属性,以便利用属性所具备的优势。这种想法听上去很有道理,但实际上并不合适。例如,我们考虑下面这个类的定义代码:这个类描述的是 Customer(客户),其中有个名为 Name 的数据成员,用来表示客户的名称。可以用大家很熟悉的写法来获取或设置这个成员:

蜀ICP备2024047804号

Copyright 版权所有 © jvwen.com 聚文网