现在的位置: 首页 > 综合 > 正文

Effective C# 摘录(3) – 使用C#表达设计

2011年05月30日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭

19:定义并实现接口优于继承类型。
   Prefer Defining and Implementing Interfaces to Inheritance。
   接口支持多重继承,可以作用于值类型,而抽象类则不可以;抽象类中可以定义字段或方法,减轻创建子类(复用)的同时增加了子类与父类之间的耦合度;子类继承接口表达的是“can-do”的关系,而子类继承抽象类表达的是“is-a”的关系。

20:明辨接口实现和虚方法重写。
   Distinguish Between Implementing Interfaces and Overriding Virtual Functions。
   派生类不能重载基类(继承接口)中的接口成员。

21:使用委托表达回调
   Express Callbacks with Delegates
   返回值总是委托链上最后一个函数调用后返回的值;在委托链中抛出的任何异常都会终止委托链的继续调用。

22:使用事件定义对外接口。
   Define Outgoing Interfaces with Events。
   观察者模式(Observer Pattern).

23:避免返回内部类对象的引用。
   Avoid Returning References to Internal Class Objects。
   四个策略来保护类的内部数据结构不被无意的修改:值类型,恒定类型,接口和包装(模式)(e.g:返回DataView而不是DataSet)。

24:声明式编程优于命令式编程.
   Prefer Declarative to Imperative Programming.
   在C#中,编程时使用特性(Attribute)就是申明式编程。使用特性来表明意图时,可以减少在大量类似的手写算法中出现逻辑错误的可能。

25:尽可能将类型实现为可序列化的类型.
   Prefer Serializable Types.
   BinaryFormatter和SoapFormatter反序列化不会调用构造函数和属性访问器(property Set/Get)(如果有的话),且能够序列化非public成员;而XML反序列化会调用构造函数和属性访问器(如果有的话),且只能够序列化public属性和字段。
   尽可能的使用默认序列化特性([SerializableAttribute]),当默认特性不满足时(e.g:在不同版本之间转换)要实现ISerializable 接口。

26:使用IComparable和IComparer接口实现排序关系。
   Implement Ordering Relations with IComparable and IComparer.
   IComparable是以提供方法来比较两个特定类型的对象;IComparer可以为排序提供一个可选的排序依据,这可以用于一些没有给你提供排序依据的类型上,提供你自己的排序依据。
   e.g:http://support.microsoft.com/kb/320727/

27:避免ICloneable接口.
   Avoid ICloneable.
   对于值类型,不应该实现ICloneable接口,而应该使用赋值语句。对于引用类型,只有在确实必要进行拷贝时,才在子类上实现对ICloneable的支持;基类在可能要对ICloneable进行支持时,应该创建一个受保护的构造函数。总之,我们应该尽量避免使用ICloneable接口。

28:避免强制类型转换操作符。
   Avoid Conversion Operators.
   通过构造函数来代替定义类型转换操作。

29:只有当强制更新基类导致问题时才考虑使用new修饰符。
   Use the new Modifier Only When Base Class Updates Mandate It.
   在子类的方法上使用new修饰符,只是隐藏了从父类继承而来的方法,而并不是重写覆盖,因此在子类的方法表中,存在两个方法槽(slot)。当子类的引用调用该方法时,是调用子类中定义的方法;而当子类转化为父类的引用时,是调用父类中定义的方法!(关于这一点,也可以参考下我以前写的《
Child类调用GrandFather类方法引发的思考》)。因此一般避免在方法上使用new修饰符。 

抱歉!评论已关闭.