一、类型的逻辑分组
从CLR的角度来看,只有两种类型:引用类型和值类型。但从框架设计来说,可以进行更细致的分类
1、引用类型,包括:类、静态类、集合、数组、异常、属性
2、值类型,包括:枚举和结构
3、接口
二、类型和命名空间
在设计一个大型框架之前,应该先决定如何把功能划分到一组功能域中,这些功能域由命名空间表示。命名空间的设计过程是一个迭代的过程,会随着一个一个版本中新的类型的加入而调整。
避免有太多的命名空间
避免把为高级场景设计的类型和为常见编程任务设计的类型放在同一个命名空间下。
三、类和接口的选择
要优先彩用类,而不是接口。与其于接口的API相比,基于类的API更容易演化,因为给类添加新成员不会破坏已有的代码。而接口则不然。
要用抽像类而不是接口来解除协定与实现之前的耦合。
要定义接口,如果需要提供一个多态的值类型层次结构的话。
四、抽象类的设计
不要在抽象类中定义公有的构造函数。由于用户无法为抽象类创建一个实例,所以为抽象类创建一个公有的构造函数是设计不当的。、
要为抽象类定义受保护的构造函数。受保护的构造函数仅仅是允许当子类型被创建时,基类能够做自己的初始化。
五、静态类的设计
要尽量少用静态类。
不要把静态类当作杂物箱。
六、接口的设计
避免使用记号接口,即没有成员的接口。如果你需要给一个具备某特征的类做记号,最好使用自定义Attribute,而不要使用接口。
不要给以发行的接口添加成员。
七、结构的设计
一般说来结构类型只应被用于小型的、单个的、不可变的,而且不会被频地装箱的值。
不要为结构提供默认的构造函数。这样使用在创建结构类型的数组的时候,不需要运行数据中每一相结构类型对象的构造函数。
要确保当所有的实例数据都为零、false或null时,结构仍处于有效状态。(意思是不要把零等值作为默认的初始化值 ,这样当其值真的为零的时候无法判断其值就是为零,还是忘记了初始化)
要为值类型实现IEquatable<T>接口。因为值类型的默认的Object.Equales()方法会导致装箱。而且它的实现也不是很高效,因为它使用的是反射。而IEquatable<T>.Equales()方法的性能就要好很多,并且不会导致装箱操作。
八、枚举的设计
枚举是一种特殊的值类型。有两种枚举类型:简单枚举和标记枚举 。
简单枚举代表一种小型的、闭合的一组选择 。标记枚举是为了支持对枚举的按位操作。
要用枚举来加强那些表示值的集合的参数、属性以及返回值的类型性。
要优先使用枚举而不是静态常量。
不要把枚举用于开放的集合(比如操作系统的版本和朋友的名字) ???
不要提供为了今后使用而保留的枚举值
要为简单枚举提供零值。可以把该值命名为“None”之类的东西。
要用复数或名词短语来为枚举类型命名
标记枚举的设计(略)
九、嵌套类型
嵌套类型是一个定义在另个一类型的作用域的类型,另一个类型称作外层类型。嵌套类型能够访问它的外层类型的所有成员。
一般来说,应该尽量少用嵌套类型。嵌套类型最适合用来对它们的外层类型的实现细节建模。
要在想让一个类型访问外层类型的所有成员(包括私有成员)时才使用嵌套类型。
不要用嵌套类型来进行逻辑分组,应该使用命名空间