`
t641339564
  • 浏览: 27462 次
  • 性别: Icon_minigender_1
  • 来自: 贵阳
社区版块
存档分类
最新评论

第3章 类型设计规范

阅读更多

ü 要确保每个类型由一组定义明确、相互关联的成员组成。

3.1. 类型和名字空间

ü 要用命名空间把类型组织成一个相关的特性域的层次结构。

 

û 避免非常深的名字空间层次。这样的层次难于浏览,因为用户不得不经常地回溯。

 

û 避免有太多的名字空间。

 

û 避免把为高级场景而设计的类型和为常见编程任务而设计的类型放在同一个名字空间中。

 

û 不要不指定名字空间就定义类型。

3.2. 类和结构之间的选择

ü 要深入了解引用类型和值类型在行为上的差异。

 

ü 作为一条经验法则,框架中的大多数类型应该是类。但是在有些情况下,由于值类型所具备的特征,使用结构会更为合适。

 

ü如果该类型的实例比较小而且生命期比较短,或者经常被内嵌在其他对象中,考虑定义结构而不要定义类。

 

û 不要定义结构,除非该类型具有以下所有特征:

Ø 它在逻辑上代表一个独立的值,与基本类型(intdouble等等)相似。

Ø 它的实例的大小小于16个字节。

Ø 它是不可变的。

Ø 它不需要经常被装箱。

在所有其他情况下,应该将类型定义为类。

3.3. 类和接口之间的选择

ü 要优先采用类而不是接口。

说明:与基于接口的API相比,基于类的API容易演化得多,因为可以给类添加成员而不会破坏已有的代码。

 

ü 要用抽象类而不是用接口来解除协定与实现之间的耦合。

说明:抽象类经过正确的设计,同样能够解除协定与实现之间的耦合,与接口所能达到的程度不相上下。

 

ü 如果需要提供一个多态的值类型层次结构的话,要定义接口。

说明:值类型不能来自其他类型继承,但它们可以实现接口。例如,IComparableIFormat table以及IConvertible都是接口,因此Int32Int64等值类型及其他基本类型,都可以是

comparableformattableconvertible的。

public struct Int32 : IComparableIFormattableIConvertible{}

public struct Int64 : IComparableIFormattableIConvertible{}

 

ü 考虑通过定义接口来达到与多重继承相类似的效果。

3.4. 抽象类的设计

û 不要在抽象类型中定义公有的或内部受保护的( protected-internal)构造函数。

说明:

只有当用户需要创建一个类型的实例时,该类型的构造函数才应该是公有的。由于你

无法创建一个抽象类型的实例,因此如果抽象类型具有公有构造函数,那么这样的设

计不仅是不当的,而且还会误导用户。

// bad design

public abstract class Claim

{

public Claim(int number){}

}

// good design

public abstract class Claim

{

// incorrect Design

protected Claim(int number){}

}

 

ü 要为抽象类定义受保护的构造函数或内部构造函数。

说明:受保护的构造函数更为常见,它仅仅是允许当子类型被创建时,基类能够做自己的初始化。

public abstract class Claim

{

protected Claim() { }

}

内部构造函数可以用来把该抽象类的具体实现限制在定义该抽象类的程序集中。

public abstract class Claim

{

internal Claim() { }

}

 

ü 要为你发布的抽象类提供至少一个继承自该类的具体类型。

说明:这有助于验证该抽象类的设计是否正确。例如,System.IOFileStreamSystem.IOStream抽象类的一个实现。

3.5. 静态类的设计

ü 要尽量少用静态类。

 

û 不要把静态类当做杂物箱。每一个静态类都应该有其明确的目的。

 

û 不要在静态类中声明或覆盖实例成员。

 

ü 要把静态类定义为密封的、抽象的,并添加一个私有的实例构造函数——如果你的编程语言没有内置对静态类的支持。

3.6. 接口的设计

ü 要定义接口,如果你需要包括值类型在内的一组类型支持一些公共的API

 

ü 考虑定义接口,如果你需要让已经自其他类型继承的类型支持该接口提供的功能。

 

û 避免使用记号接口(没有成员的接口)。如果你需要给一个具备某特征(记号)的类做记号,一般来说,最好使用自定义attribute而不要使用接口。

 

ü 要为接口提供至少—个实现该接口的类型。

例如:这有助于验证接口的设计。例如,System.Collections.ArrayListSystem.Collections.IList接口的一个实现。

 

ü 要为你定义的每个接口提供至少一个使用该接口的API(一个以该接口为参数的方法,或是一个类型为该接口的属性)。这有助于有助于验证接口的设计。

例如:List<T>.Sort使用了IComparer<T>接口。

 

û 不要给已经发行的接口再添加成员。

说明:这样做会破坏该接口的实现。为了避免版本的问题,应该创建一个新的接口。

3.7. 结构的设计

û 不要为结构提供默认的构造函数。

 

ü 要确保当所有的实例数据都为零、falsenull(如果合适)时,结构仍处于有效状态。这可以防止在创建一个结构的数组时创建出无效的实例。

例如:下面的结构设计得不正确。带参数的构造函数有意用来确保状态有效,但是在创建该结构的数组时,这个构造函数没有被执行,因此所有的实例字段都被初始化为0,而对该类型来说这并不是一个有效的状态。

//bad Design

public struct PositiveInteger

{

int value;

public PositiveInteger(int value)

{

if (value <= 0)

throw new ArgumentException(); }

this.value = value;

}

public override string ToString()

{

return value.ToString();

}

}

 

通过确保默认的状态(本例中的value宇段为0)是该类型的有效逻辑状态,这个问题

可以得到解决。

//good Design

public struct PositiveInteger

{

int value;

public PositiveInteger(int value)

{

if (value <= 0)

throw new ArgumentException(); }

this.value = value - 1;

}

public override string ToString()

{

return (value + 1).ToString();

}

}

 

ü 要为值类型实现IEquatable<T>

说明:值类型的ObjectEquals方法会导致装箱,而且它的默认实现也并不非常高效,因为它使用了反射。IEquatable<T>Equals的性能要好得多,而且能够实现为不会导致装箱。

 

û 不要显式地扩展System.ValueType,事实上大多数编程语言不允许这样做。

3.8. 枚举的设计

ü 要用枚举来加强那些表示值的集合的参数、属性以及返回值的类型性。

 

ü 要有限使用枚举而不要使用静态常量。

//Avoid the following

public static class Color

{

public static int Red = 0;

public static int Green = 1;

public static int Blue = 2;

}

//Favor the following

public enum Color

{

Red,

Grean,

Blue

}

 

û 不要把枚举用于开放的集合(比如操作系统的版本、朋友的名字等)

 

û 不要提供为了今后使用而保留的枚举值。

 

û 避免显式暴露只有一个值的枚举。

 

û 不要把sentinel值包含在枚举值中。

例如,下面的代码显示了一个带sentinel值的枚举,这个附加的sentinel值用来表示枚举的最后一个值,其目的是用于范围检查。在框架设计中,这是不好的做法。

public enum DeskType

{

Circular = 1,

Oblong = 2,

Rectangular = 3,

LastValue = 3 //this sentinel should not be here

}

 

public void OrderDesk(DeskType desk)

{

if (desk > DeskType.LastValue)

throw new ArgumentOutOfRangeException(); }

}

 

ü 框架的开发人员应该用真实的枚举值来执行检查,而不应该依赖于sentinel值。

public void OrderDesk(DeskType desk)

{

if (desk > DeskType.Rectangular||desk<DeskType.Circular)

throw new ArgumentOutOfRangeException(); }

}

 

ü 要为简单枚举类型提供零值。

例如:可以考虑把该值称为“None”之类的东西。如果这样的值不适用于某个特定的枚举那么应该把该枚举中最常用的默认值赋值为零。

public enum Compression

{

None = 0,

GZip,

Deflate

}

public enum EventType

{

Error = 0,

Warning,

Information

}

 

ü 考虑用Int32(大多数编程语言的默认选择)作为枚举的基本实现类型,除非下面的

任何一条成立:

Ø 该枚举是一个标记枚举,而你有超过32个标记,或预计今后会有更多的标记。

Ø 为了更方便地与需要不同大小的枚举的非托管代码进行互操作,基本的实现类型必须是Int32之外的类型。

Ø 更小的底层实现类型可能会节省相当的空间。

 

ü 要用复数名词或名词短语来命名标记枚举,用单数名词或名词短语来命名简单枚举。

 

û 不要直接扩充System.Enum

说明:SystemEnurn是一个特殊的类型,被CLR用来创建用户定义的枚举。大多数编程语言提供了相应的编程元素让你访问这项功能。例如,在C#中,enum关键字被用来定义一个枚举。

3.8.1. 标记枚举的设计

ü 要对标记枚举使用System.FlagsAttribute。不要把该attribute用于简单枚举。

[Flags]

public enum AttributeTargets

{ }

 

ü 要用2的幂次方作为标记枚举的值,这样就可以通过按位或操作自由地组合它们。

[Flags]

public enum WatcherChangeTypes

{

Created = 0x0002,

Deleted = 0x0004,

Changed = 0x0008,

}

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    公园设计规范【完整版】.pdf

    公园设计规范【完整版】第三节 园内主要用地比例规定,公园内部用地比例应根据公园类型和陆地面积确定。其绿化、建筑、园路及铺装场地等用地的比例应符合表2.3.1的规定。在符合公园设计规范【完整版】的要求下,公园...

    《建筑抗震设计规范》GB50011-2010(2)第六章--柯总.pdf

    《建筑抗震设计规范》GB50011-2010(2)第六章针对多层和高层钢筋混凝土房屋的抗震设计规范进行了修订,旨在总结国内外地震灾害的经验教训,尤其是2008年汶川地震的深刻教训,以提高建筑的抗震性能。修订工作由清华...

    C 语言程序设计第2章 数据类型

    在C语言程序设计中,第二章“数据类型”是编程基础的重要组成部分,它涵盖了程序中数据的分类、表示和操作。下面将详细解释这一章的主要知识点。 首先,C语言的数据类型主要包括整型(int)、实型(float和double)...

    静电放电防护设计规范和指南

    第三章 静电放电的危害 5 3.1 ESD造成元器件失效 5 3.2 ESD引起信息出错,导致设备故障 5 3.3 高压静电吸附尘埃微粒 6 第四章 ESD防护设计指南 6 4.1 设备的ESD防护设计要求 6 4.2 PCB的ESD防护设计要求 7 4.3 通讯...

    .NET设计规范:约定、惯用法与模式(第2版)克瓦林纳 3/5

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记枚举的...

    《建筑地基基础设计规范》.pdf

    该规范共有27个强制性条文,分别分布在第三章、第五章、第六章、第七章、第八章、第九章和第十章。 二、设计原则 《建筑地基基础设计规范》明确规定了地基基础设计必须坚持因地制宜、就地取材、保护环境和节约资源...

    .NET设计规范:约定、惯用法与模式(第2版)克瓦林纳 4/5

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记枚举的...

    .NET设计规范:约定、惯用法与模式(第2版)1/5

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记枚举的...

    .NET设计规范约定 惯用法与模式

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记...

    1数据库设计规范.doc

    **第3章 使用规范** 3.1 **综合** - 只有数据库管理员能修改数据库结构,其他人需提交修改申请。 - 数据访问层推荐使用存储过程,避免直接DML操作。 - 存储过程应专注于单一任务,复杂的任务可分解为多个简单存储...

    .NET设计规范:约定、惯用法与模式(第2版)克瓦林纳 2/5

    第4章 类型设计规范  4.1 类型和名字空间  4.2 类和结构之间的选择  4.3 类和接口之间的选择  4.4 抽象类的设计  4.5 静态类的设计  4.6 接口的设计  4.7 结构的设计  4.8 枚举的设计  4.8.1 标记枚举的...

    冷库设计规范标准.pdf

    **第三章 建筑** 3.1.1 条至3.1.5 条涉及库址选择和库区布置,考虑因素包括风向、交通、卫生条件、水源和电源等。氨压缩机房和变配电室的位置也需靠近冷间,以确保高效运行和维护便利。 这些规范为冷库设计提供了...

    C++程序设计(04737)第三章的例子的代码

    在本资源中,我们主要关注的是"C++程序设计(04737)第三章"的相关实例代码。C++是一种强大的、面向对象的编程语言,广泛应用于系统软件、应用软件、游戏开发、设备驱动程序等多个领域。04737可能是课程编号或某种标识...

    数据库系统概论:第3章 数据库设计和规范化1.ppt

    规范化是实现良好关系模式设计的过程,通常包括一系列的范式,如第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、第四范式(4NF)和第五范式(5NF,也称为项目依赖范式)。每个更高层次的范式都要求满足更严格的数据依赖...

    JAVA【第3章:Java基础程序设计】_Java数据类型

    在Java编程语言中,数据类型是程序设计的基础,它们决定了变量可以存储的值的种类和范围。本章将深入探讨Java中的数据类型,分为两大类:基本数据类型和引用数据类型。 1. 基本数据类型: - 整型:Java提供了四种...

    手机上网WAP业务设计规范

    #### 第三章 业务内容管理和维护 - **业务内容要求** - **总体要求**:所有SP必须遵守国家相关法律法规,包括但不限于《互联网信息管理办法》、《计算机信息网络国际联网安全保护管理办法》等,同时遵守中国移动的...

    数据库系统概论:第3章 数据库设计和规范化3.ppt

    常见的规范化级别包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和巴斯-科德范式(BCNF)等。每个阶段都有特定的规范准则,确保数据在逻辑上和物理上的高效组织。例如,如果"成绩"表中包含学生的所有信息,那么可能...

    C++面向对象程序设计电子课件第三章

    在C++面向对象程序设计的第三章中,我们聚焦于数据存储与流程控制,这是编程中的基础概念,对于创建灵活且可维护的程序至关重要。在上一章中,通过使用string类,我们改进了一个简单的输出问候语的程序,使其具有更...

    数据库设计规范

    第2章【设计规范】强调了遵循3NF(第三范式)的原则,以消除数据冗余和提高数据一致性。每个表应有唯一标识符(主键),字段设计时考虑数据类型,例如金额字段使用decimal以保证精度,时间字段使用DateTime确保时间...

Global site tag (gtag.js) - Google Analytics