第 4 章:类型设计规范

4.1 类型和命名空间

  要用命名空间把类型组织成一个由相关的功能区所构成的层次结构中。

  避免非常深的命名空间层次。因为用户需要经常回找,所以这样的层次浏览起来很困难。

  避免有太多的命名空间。

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

  不要不指定类型的命名空间就定义类型。

  要把那些为基本命名空间提供设计时功能的类型放在带“.Design”后缀的命名空间中。

  要把那些为基本命名空间提供自定义权限的类型放在带“.Permissions”后缀的命名空间中。

  要把那些为基本命名空间提供互操作功能的类型放在带“.Interop”后缀的命名空间中。

  要把所有位于主互操作程序集中的代码放在带“.Interop”后缀的命名空间中。

4.2 类和结构之间的选择

  考虑定义结构而不要定义类 - 如果该类型的实例比较小而且声明周期比较短,或者是经常被内嵌在其它对象中。

  避免定义结构,除非该类型具有以下所有特征。

    它在逻辑上代表一个独立的值,与基本类型(int、double 等等)相似;

    它的实例的大小小于 16 个字节;

    它是不可变的;

    它不需要经常被装箱。

  

4.3 类和接口之间的选择

  要优先定义类而不是接口

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

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

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

  

4.4 抽象类的设计

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

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

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

  

4.5 静态类的设计

  要尽量少用静态类。

  不要把静态类当做是杂物箱。

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

  要把静态类定义为密封的、抽象的,并添加一个私有的实例构造函数 - 如果编程语言不直接支持静态类。

  

4.6 接口的设计

  要定义接口 - 如果想让一组包括值类型在内的类型支持一些公共的 API。

  考虑定义接口 - 如果想让已经继承自其它基类的类型支持该接口提供的功能。

  避免使用记号接口(没有成员的接口)。

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

  要为每个接口提供至少一个使用该接口的 API(一个以该接口为参数的方法,或是一个类型为该接口的属性)。

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

4.7 结构的设计

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

  不要定义可变的值类型。

  要确保当结构实例的所有数据都为 0、false 或 null(如果合适)时,结构仍处于有效状态。

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

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

4.8 枚举的设计

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

  要优先使用枚举而不要使用静态常量。

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

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

  避免显示地暴露只有一个值的枚举。

  不要在枚举中包含 sentinel 值。

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

  考虑以 Int32 为载体来实现枚举(大多数编程语言的默认选择),除非下面的任何一条成立。

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

  不要直接扩充 System.Enum。

  要对标记枚举使用 System.FlagsAttribute。不要把该修饰属性用于简单枚举。

  要用 2 的幂次方作为标记枚举的值,这样就可以使用按位 OR 操作来自由地组合他们。

  考虑为常用的标记组合提供特殊的枚举值。

  避免让创建的标记枚举包含某些无效的组合。

  避免把 0 用作标记枚举的值,除非该值表示“所有标记都被清除”,而且按下一条规范进行了适当地命名。

  要把标记枚举的 0 值命名为 None。对标记枚举来说,该值必须始终表示“所有标记均被清除”。

  考虑给枚举添加值,尽管要冒一点兼容性的风险。

  

4.9 嵌套类型

  要在想让一个类型能够访问外层类型的成员时才使用嵌套类型。

  不要用公共嵌套类型来进行逻辑分组,应该用命名空间来达到这一目的。

  避免公开地暴露嵌套类型。除非是只需在极少数的情况下声明嵌套类型的变量,比如派生子类时,或者其它需要定制的高级场景中。

  不要使用嵌套类型 - 如果该类型可能会被除了它的外层类型之外的类型引用。

  不要使用嵌套 - 如果需要让客户代码来实例化它们。如果某个类型具有公有构造函数,那么他不应该被嵌套在其它类型中。

  不要把嵌套类型定义为接口的成员,许多编程语言不支持这样做。

4.10 类型和程序集元数据

  要在包含公共类型的程序集中使用 CLSCompliant(true) 修饰属性。

  要在包含公共类型的程序集中使用 AssemblyVersionAttribute 修饰属性。

  考虑在程序集版本号中使用 <V>、<S>、<B>、<R> 的格式。其中 V 是主版本号,S 是服务版本号,B 是构建号,R 是构建修订号。

  要在程序集中使用下面的修饰属性来提供额外的信息。

  考虑在程序集中使用 ComVisible(false)。可供 COM 调用的 API 需要特别地设计。

  考虑在程序集这种使用 AssemblyFileVersionAttribute 和 AssemblyCopyrightAttribut,其目的是为了提供与程序集有关的额外信息。

《.NET 设计规范》第 4 章:类型设计规范的更多相关文章

  1. .NET设计规范————类型设计规范

    类型设计规范 从CLR的角度看,只有值类型和引用类型两种类型,但是从框架设计的角度我们把类型从逻辑上分了更多的组.如下所示: 类是引用类型的一般情况,占了框架中的大多情况,类的流行归于它支持面向对象的 ...

  2. Javascript权威指南——第二章词法结构,第三章类型、值和变量,第四章表达式和运算符,第五章语句

    第二章 词法结构 一.HTML并不区分大小写(尽管XHTML区分大小写),而javascript区分大小写:在HTML中,这些标签和属性名可以使用大写也可以使用小写,而在javascript中必须小写 ...

  3. 《JS权威指南学习总结--第三章类型、值和变量》

    第三章 类型.值和变量 内容要点 一.数据类型 1.在编程语言中,能够表示并操作的值的类型称做数据类型 2.JS的数据类型分为两类: 原始类型:数字.字符串和布尔值 对象类型 3.JS中有两个特殊的原 ...

  4. 20190908 On Java8 第十九章 类型信息

    第十九章 类型信息 RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息. Java 主要有两种方式在运行时识别对象和类信息: "传 ...

  5. 4.类型设计规范《.NET设计规范》

    类是引用类型的一般情况,占了框架中的大多情况,类的流行归于它支持面向对象的特征,以及它的普遍的适用性,基类和抽象类是两个特殊的逻辑分组,它们与扩张性有关. 由于CLR不支持多继承,接口类型可以用来模拟 ...

  6. 第六章 类型(class)和成员基础

    1. 概述 本章讲述如何在一个类型中定义不同种类的成员. 2. 名词解释 3. 主要内容 3.1 类型的各种成员 在一个类型中,可以定义0个或多个以下种类的成员: ① 常量:常量就是指出数据值恒定不变 ...

  7. C# 语言规范_版本5.0 (第4章 类型)

    1. 类型 C# 语言的类型划分为两大类:值类型 (Value type) 和引用类型 (reference type).值类型和引用类型都可以为泛型类型 (generic type),泛型类型采用一 ...

  8. Javascript权威指南阅读笔记--第3章类型、值和变量(1)

    之前一直有个想法,好好读完JS权威指南,便于自己对于JS有个较为全面的了解.毕竟本人非计算机专业出生,虽然做着相关行业的工作,但总觉得对于基础的掌握并没有相关专业学者扎实,正好因为辞职待业等原因,还是 ...

  9. C# Language Specification 5.0 (翻译)第四章 类型

    C# 语言的类型分为两大类:值类型(value type)和引用类型(reference type),而它们又都同时具有至少一个类型形参的泛型类型(generic type).类型形参(type pa ...

随机推荐

  1. LevelDB的源码阅读(四) Compaction操作

    leveldb的数据存储采用LSM的思想,将随机写入变为顺序写入,记录写入操作日志,一旦日志被以追加写的形式写入硬盘,就返回写入成功,由后台线程将写入日志作用于原有的磁盘文件生成新的磁盘数据.Leve ...

  2. 分享一个android静默安装,安装后重新启动app的方法

    一:需求简介 之前boss提出一个需求,运行在广告机上的app,需要完成自动升级的功能,广告机是非触摸屏的,不能通过手动点击,所以app必须做到自动下载,自动安装升级,并且安装完成后,app还要继续运 ...

  3. 整理C++面试题for非CS程序猿——更新至【48】

    结合网上的C++面试题+自己的面经,进行整理记录,for我这种非CS的程序猿.(不定期更新,加入了自己的理解,如有不对,请指出) [1] new/delete和malloc/free的区别和联系? 1 ...

  4. HDU Today(最短路)

    http://acm.hdu.edu.cn/showproblem.php?pid=2112 HDU Today Time Limit: 15000/5000 MS (Java/Others)     ...

  5. 解决指向iframe的target失效

    今天遇到一个bug. 主页面中点击左侧导航栏[某]项后,右侧的iframe页面加载到了新窗口.之后,所有选项的iframe加载都异常. 检查<a>标签target="main&q ...

  6. 浅谈MySQL集群高可用架构

    前言 高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.对于一个系统而言,可能包含很多模块,比如前端应用,缓存,数据库,搜索,消息队列等,每个模块都需要做到高可用,才能 ...

  7. light oj 1184 Marriage Media

    题目: You run a marriage media. You take some profiles for men and women, and your task is to arrange ...

  8. yourphp目录结构

    Yourphp企业网站管理系统是一款完全开源免费的PHP+MYSQL系统.核心采用了Thinkphp框架等众多开源软件,同时核心功能也作为开源软件发布的网站后台管理系统. 二.目录说明 /Cache ...

  9. WPF与Win32互操作

    一.WPF如何使用HWND 当您创建WPF Window时,WPF会创建顶级HWND,并使用HwndSource将Window及其WPF内容放入HWND中.应用程序中其余的WPF内容共享此单个HWND ...

  10. block一点也不神秘————如何利用block进行回调

    我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数时候回调是比通知方便的,所以何乐而不为呢?如果你不知道回调使用的场景,我们来假设一下: 1.我现在玩手机 2.突然手机没有电了 3.我 ...