.NET应用开发编码规范x_第1页
.NET应用开发编码规范x_第2页
.NET应用开发编码规范x_第3页
.NET应用开发编码规范x_第4页
.NET应用开发编码规范x_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1. 前言1.1. 目的本文档用于规范.NET代码编写工作。任何代码编写工作都需按照此规范执行。1.2. 约定在每小节下面都有一些要求必须遵守,或者建议遵守的规范。通过O(Obey)表示必须遵守,A(advise)表示建议遵守。O2-001XXX。表示第一章第一个必须遵守的规范。A2-001XXX。表示第一章第一个建议遵守的规范。1.3. 参考资料编号资料名称简介作者日期出版单位001Framework Design Guidelines:Conventions,Idioms,and Patterns for Reusable.NET Lbraries框架设计师和开发人员的权威指南。Krzyszof CwalinaBrad Abrams2006年7月Microsoft Corporation002Code CompleteSteve、McConnell2006年Microsoft Corporation1.4. 术语序号术语备注123456789102. 命名规范2.1. 通用命名约定本节描述了一些通用的命名约定,它们涉及到单词的选择、单词缩写和首字母缩写词的使用规范以及如何避免使用编程语言特有的名字。 2.1.1. 单词的选择A. O2-001要为标识符选择易于阅读的名字; a) 解释对标识符的名字来说,很重要的一点是要一目了然。标识符的名字应该清楚地说明每个成员做什么,以及每个类型和参数表示什么。b) 示例一个命为HorizontalAlignment 的属性就比AlignmentHorizontal 更易于阅读。 B. O2-002要更看重可读性,而不是更看重简短性。a) 解释名字的意思清楚要比长度短更重要。名字应该与场景、系统的逻辑组成或物理组成以及为人熟知的概念相对应,而不应该与技术或框架相对应。b) 示例属性名CanScrollHorizontally要胜于ScrollableX(不太明显地引用了X坐标轴)。C. O2-003不要使用下划线、连字符以及其他任何既非字符也非数字的字符。a) 解释用大小写来区分单词,而不是用下划线、连字符或其它字符。b) 示例不要使用user_name来表示用户名属性,而是用UserName。D. O2-004不要使用匈牙利命名法。a) 解释匈牙利命名法过于繁琐,命名应该用于说明标识符的含义而不是它的类型。b) 示例不要使用CDocument来定义文档类,而是使用Document。E. O2-005不要使用与广泛使用的编程语言的关键字有冲突的标识符。a) 解释根据CLS(公共语言规范)的第4条规则,所有符合规范等语言必须提供一种机制,允许用户访问以该语言的关键字来命名的标识符。例如,C#在这种情况下使用符号作为转义机制(escape mechanism)。但是,由于在使用方法时,用转义序列(escape sequence)要比不用转义序列麻烦得多,因此避免使用常见的关键字仍然是个好习惯。b) 示例 不要定义一个Type class;的变量来表示类型,而应该用Type type;2.1.2. 使用单词缩写和首字母缩写词A. O2-006不要使用缩写词和缩约词作为标识符名字的一部分a) 解释一般来说,不要在标识符中使用单词缩写或首字母缩写词。正如前面所讲,对名字来说,可读性比简短更重要。另外有一点也同样重要,即不要使用未被广泛接受的单词缩写和首字母缩写词,也就是说,大多数非领域专家的人能够立刻知道它们是什么意思。b) 示例要用GetWindow,而不要用GetWin。B. O2-007不要使用未被广泛接受的首字母缩写词,即使是被广泛接受的首字母缩写词,也应该在必须的时候才使用a) 解释例如,UI用来表示User Interface,HTML用来表示 Hypertext Markup Language。在框架的标识中使用它们仍是不好的做法。2.1.3. 避免使用语言特有的名字对那些所谓的基本类型,CLR平台上的编程语言通常都有自己的名字(别名)来称呼它们。例如,int 是C#中System.Int32 的别名。为了确保框架能够充分利用跨语言协作-CLR的核心特性之一,避免在标识中使用语言特有的类型名是很重要的。A. O2-008要给类型名使用语义上有意义的名字,而不要使用语言特有的关键字b) 示例例如:GetLength这个名字比GetInt要好。B. O2-009要使用CLR的通用类型名,而不要使用语言特有的别名-如果除了类型之外,标识符没有其他的语义a) 示例一个把类型转换为System.Int64的方法应该被命名为ToInt64,而不是Toloong(因为System.Int64是CLR类型名,它对应于C#特有的别名long)。表3-3列出了有别名的基本类型在CLR中的类型名(以及与C#、Visual Basic、C+相对应的类型名)。 C. O2-010要使用常见的名字,比如value 或item,而不要重复类型的名字-如果除了类型之外, 标识符没有其他的语义,而且参数的类型不重要a) 示例类提供的这些方法可以把各种不同的数据类型写入流中:void Write(double value);void Write(float value);void Write(short value); 2.1.4. 为已有API的新版本命名有时无法将一个新特征添加到一个已有的类型中去,即使已有类型的名字意味着它是新特征的最佳归宿。在这种情况下需要添加一个新类型,但由于要给新类型找一个好的新名字,因此这通常给框架设计师出了难题。类似地,在需要提供额外的功能时,经常会无法对已有的成员进行扩展或重载,为此,只能用新名字来添加新成员。下面的规范描述了当用新类型和新成员接替或取代已有的类型或成员时,如何为它们选择名字。A. O2-011要在创建已有API的新版本使用与旧API相似的名字。这有助于突出API之间的关系a) 示例class AppDomain Obsolete(“AppDoMain.SetCachePath has been deprecated”) public void SetCachePath(String psth). class AppDomainSetup public string CachePath get; set; B. O2-012要优先使用后缀而不是前缀来表示已有API的新版本。 这有助于在浏览文档或使用Intellisense 时发现新版本。由于大多数浏览器和Intellisense按字母的顺序显示标识符,因此旧API与新API在位置上会非常接近 C. A2-001考虑使用全新但有意义的标志符号,而不是简单地给已有标识符添加后缀或前缀。D. O2-013要使用数字后缀来表示已有API的新版本,如果已有API的名字是唯一有意义的名字(也就是说,它是一个工业标准),不适宜添加后缀(或改名)E. O2-014不要在标识符中使用“Ex”(或类似的)后缀来区分相同API的不同版本。 a) 示例public class CarEx /the wrong way F. O2-015要在引入对64位整数(long)而非32位整数进行操作的新版本API时使用“64”后缀。只有当已经存在32位的API时才需要采用这种方法,对只有64位版本的全新API则不需要这要做2.2. 大小写约定因为CLR支持许多编程语言,这些语言有的区分大小写,有的不区分,所以不应该只用大小写来区分名字。但是,大小写对增强名字可读性的重要性怎么强调也不过分。本章中的规范展示了一种使用大小写的简单方法,如果一致地使用,那么会使类型、成员以及参数的标识符更易于阅读。2.2.1. 标识符的大小写规则为了区分一个标识符中的多个单词,把标识符中的每个单词的首字母大写。不要用下划线来区分单词,或者在标识符中的任何地方使用下划线。有两种合适的方法来大写标识符中的字母,这取决于所使用的标识符:PascalCasingcalmelCasingPascalCasing约定被用于除了参数名、变量名、私有字段名之外的所有标识符,它把标识符中每个单词的首字母(包括长度为两个字符以上的首字母缩写词)大写,如下面的例子所示: HtmlTag两个字母长的首字母缩写词是一个特例,在这种情况下两个字母都要大写,如下面的标识符所示:IOStreamcamelCasing约定用于参数、变量、私有字段的名字,它把标识符中除了第一个单词之外的所有单词的首字母大写,如下面的例子所示。在例子中,如果camolCasing风格的标识符以两个字母长的首字母 ,那么两个字母都要小写。ioStreomhtmlTagA. O2-016要把PascalCasing用于由多个单词构成的名字空问、类型以及成员的名字a) 示例使用Textcolor而不是Textcolor或Text_color。单个单词(比如Button)直接首字母大写。始终作为一个单词的复合词(比如endpoint)视为一个单词,只有第一个字母大写。B. O2-017要把camelCasing用于参数的名字b) 示例表2-1 不同类型的标识符的大小写规则 -标识符大小写样例-命名空间:Pascal namespace System.Security .类型: Pascalpublic class StreamReader接口:Pascalpublic class StreamReader方法:Pascal public class Object public virtual string ToString();属性: Pascal public class Stringpublic int Length get;事件 Pascal public class Processpublic event EventHandler Exited;字段(静态)Pascal public MessageQueuepublic static readonlyTimeSpanInfiniteTimeout;枚举值 Pascal FileMode Append, 参数 Camel public class Convert public static intToInt32(string value ); -2.2.2. 首字母缩写词的大小写 一般来说,避免在标识符的名字中使用首字母缩写词是很重要的,除非它们是普遍使用的,能够立刻使用框架的人所理解。例如,HTML、XML和IO很容易理解,但不怎么常用的首字母缩写词绝对应该避免。 2.3. 程序集和DLL的命名程序集是一个部署单元,同时还代表托管代码程序的身份。虽然程序集可以分布在一个或多个文件中,但一般来说一个程序集仅与一个DLL想对应。因此,本节只讨论DLL的命名约定,程序集的命名约定与次类似。 命名空间与DLL和程序集是不同的概念。命名空间对开发人员来说是一组逻辑实体,而DLL和程序集则是在打包和部署时的一个单元。DLL可以因产品的组织及其他原因而包含多个命名空间。由于命名空间的组织方法与DLL不同,因此应该单独设计。例如,如果决定把DLL命名为MyConpany.MyTechnology,这并不意味着DLL必须包含名为MyCompany.MyTechnology的命名空间。 A. O2-018要为程序集和DLL选择提示性的名字a) 示例比如System.Data,这样很容易就知道它的大致功能。程序集和DLL的名字不一定要和命名空间相对应,但在给程序集命名时遵循命名空间的名字也是合情合理的。 考虑按照下面的模式给DLL命名 .dll 其中包含一个或多个以点号分隔的子句 Microsoft.VisualBasic.dllMicrosoft.VisualBasic.Vsa.dll Fabrikam.Security.dll Litware.Controls.dll 2.4. 命名空间的命名与其他的命名规范一样,为命名空间命名的目的是清晰,这样对使用框架的程序员来说,他们就能立刻知道一个命名空间中大概有些什么。下面的模版给出了命名空间命名的一般规则: .(|). A. O2-019要用公司名称作为命名空间的前缀,这样就可以避免与另一家公司使用相同的名字a) 示例微软提供的Microsoft Office 自动化API应该放在Microsoft.Office命名空间中。 B. O2-020要用稳定的、与版本无关的产品名称作为命名空间的第二层。C. O2-021不要根据公司的组织架构来决定命名空间的层次结构,因为公司内部组织的的名称一般来说不会持续太长的时间D. O2-022要使用PascalCasing大小写风格,并用点号来分隔命名空间中的各部分a) 示例Microsoft.Office.PowerPoint,如果商标使用了非传统的大小写风格,那么即使该跟个与常规的大小写风格相背,也还是应该遵循商标的大小写风格。 E. A2-002考虑在适当的时候在命名空间中使用复数形式a) 示例要用System.Collections,而不要用System.Collection,但是,商标名称和首字母缩写词例外。例如,要用System.IO,而不要用System.IOs。 F. O2-023不要用相同的名字来命名命名空间与位于该命名空间中的类型a) 示例不要先将命名空间命名为Debug,然后又在该命名空间中提供一个名为Debug的类。许多编译器都要求用户在使用这样的类型时要加上完整的限定符。 这些guifan 涵盖了命名空间命名的一般规范,下一节将为某些特殊的子命名空间提供一些有针对性的规范。 命名空间与类型名的冲突命名空间用来把类型组织成一个逻辑的、易于浏览的层次结构。对解决在导入多个命名空间时可能引起的类型名的二义性,它们同样是不可或缺的。但即便如此,对那些通常会在一起使用的不同命名空间来说,仍不应该以此为借口在类型之间引入二义性。在常见的场景中,开发人员应该不需要给类型名加上限定符。 G. O2-024不要引入太一般化的类型名a) 示例比如Element、Node、Log 以及Message。这样的名字很可能会在常见的场景中引起类型名的冲突。应该给这些一般化的类型名加上修饰语( FormElement、XmlNode、EventlogSoapMessage)。 对不同类型的命名空间,有具体的规范来避免类型名的冲突。命名空间可以分为下面的类别:应用程序模型命名空间(application model namespace)基础设施命名空间(infrastructure namespace)核心命名空间(core namespace)技术命名空间组(technology namespace group)2.4.1. 应用程序模型命名空间 属于单个应用程序模型的命名空间经常在一起使用,但是它们几乎从不和属于其他应用程序模型的命名空间一起使用。例如,System.Windows.Forms命名空间很少和System.Web.UI命名空间一起使用。下面列出了众所周知的应用程序模型的命名空间组。 System.Windows* System.Web.UI*A. O2-025不要给位于同一个应用程序模型的命名空间中的类型起相同的名字b) 示例不要给System.Web.UI.Adapters 命名空间增加一个名为Page 的类型,因为System.Web.UI 命名空间已经包含了一个名为Page的类型。2.4.2. 基础设施命名空间这个类别包含了一些在开发常用的应用程序时很少会导入的名字名剑。a) 示例.Design命名空间主要在开发编程工具时使用。避免和这些命名空间中的类型产生冲突并不是至关重要的。 System.Windows.Forms.Design *.Design *.Permissions2.4.3. 核心命名空间核心命名空间包括了所有的System命名空间,但应用程序模型命名空间和基础设施命名空间除外。核心命名空间包含System、System.IO、System.Xml 以及System.Net 等等。A. O2-026不要给类型起会与核心命名空间中的任何类型冲突的名字a) 示例绝对不要用Stream来作类型名。它会和System.IO.Stream产生冲突,而后者是一个很常用的类型。B. O2-027同样的道理,不要给System.Diagnstics.Events命名空间增加一个名为EventLog的类型a) 解释因为System.Diagnostics命名空间已经包含了一个名为EventLog的类型。 2.4.4. 技术命名空间组这个类别包括所有那些以相同的两个前缀(.*)开始的命名空间,比如Microsoft.Build.Utilities和Microsoft.Build.Tasks。属于同一个技术的类型彼此之间不产生冲突是很重要的。 A. O2-028不要给类型起会与位于同一技术中的其他类型产生冲突的名字B. O2-029不要在技术命名空间和应用程序模型命名空间的类型之间引入类型名冲突(除非不打算将该技术与应用程序模型一起使用)2.5. 类、结构和接口的命名一般来说,类型名应该是名词词组,因为它们代表系统中的实体。一条很好的经验法则是,如果无法为类型找到一个名词词组,那么可能应该重新考虑该类型的总体设计。 另一个重要的考虑因素是最易于识别的名字应该用于最常用的类型,即便从纯技术的角度来说该名字更适合其他某个不太常用的类型。例如,在一个主要场景中用来把打印作业提交到打印队列的类型应该命名为Printer,而不是PrintQueue,虽然从技术上说,该类型代表一个打印队列而不是物理设备(打印机),但是从场景的角度来说,PRINTER 是最理想的名字,因为大多数人对提交打印作业感兴趣,对与物理打印机相关的其他操作(如配置打印机)并不感兴趣。如果需要提供另一个类型来对应物理打印机 。如果需要提供另一个类型来对应物理打印机,比如用在配置场景中,那么该类型可以被命名为PrinterConfiguration或PrinterManager。 与此相似,最常用的类型名应该反映出使用场景,而不是继承层次。大多数用户只使用继承层次的叶结点,它们肌肤不会关心类层次的结构。然而,API设计者常常把继承层次作为选择类型名的最重要的标准。例如 ,Stream、StreamReader、TextReader、StringReader以及FileStream都相当好地描述了每个类型在继承层次中的位置,但它们模糊了对大多数用户来说最为重要的信息:为了从文件中读取文本,哪个类型才是他们需要实例化的。 下面的命名规范使用于一般的类型名。 A. O2-030要用名词或名词词组来给类型命名,在少数情况下也可以用形容词词组来给类型命名B. O2-031在命名时要使用PascalCasing 大小写风格a) 解释这使类型名和方法区分开,后者用动词词组来命名。 C. O2-032不要给类名加前缀(例如“C”)D. A2-003考虑让派生类的名字以基类的名字结尾a) 解释这样可读性会非常好,而且能清楚地解释它们之间的关系。b) 示例ArgumentOutOfRangeException,它是一种Exception;SerializableAttribute,它是一种Attribute。但是,在运用这一条时,很重要的一点是要做出合理的判断;即使Button类的名字中没有出现Control字样,它仍是一种Control事件。下面是一些正确命名的例子:public class FileStream:Streampublic class Button :Control E. O2-033要让借口的名字以字母I开头,这样可以显示出该类型是一个接口a) 示例Icomponent(描述性的名字)、IPersistable(形容词)都是恰当的接口名字。同其他类型名一样,要笔描使用单词缩写。 F. O2-034要确保一对类/接口及其标准实现-Component类为例说明本条规范a) 示例public interface Icomponent public class Component : Icomponent2.5.1. 泛型类型参数的命名泛型是.NET框架2.0版的一个主要新特征,它引入了一种称为类型参数(type parameter) 的新标识符。下面的规范描述了与类型参数有关的命名约定。A. O2-035要用描述性的名字来命名泛型类型参数-除非一个字母就足够了,而且描述性的名字并不能增添什么价值B. A2-004考虑用T来命名参数类型如果类型只有一个类型参数,且类型参数只有一个字母a) 示例public int Icomparepublic delegate bool Ptedicate(T item);public struct Nullable where T : structC. O2-036要给描述性的类型参数名加上T前缀a) 示例public interface TsessionChannel where Tsession:Tsession Tsession Session get; D. A2-005考虑在类型参数名中显示出施加于该类型参数上的限制a) 示例可以把一个被限制为ISession的类型参数命名为TSession。2.5.2. 常用类型的命名如果要从.NET框架所包含的类型派生新类型,或者要实现.NET框架中的类型,那么遵循本节中的规范是非常重要的。A. O2-037要遵循表2-3中描述的规范如果要从.NET框架的类型派生新类,或者要实现.NET框架中的类型a) 解释这些后缀的规范适用于某个特定的类型为基类的整个继承层次。例如,不仅仅是直接派生自System.Exception的类型才需要后缀,那些派生自Exception的子来信的类型也需要。应该把这些后缀留给那些在下表中列出的类型,对那么派生自或实现其他类型的类型来说,不应该使用这些后缀。b) 示例 表 2-3 派生自或实现某些特定的核心类型的命名规则-基类 派生类型/实现类型的规范-System.Attribute 要给自定义的attribute 类添加“Attribute”后缀System.EventArgs 要添加“EventArgs”后缀 2.5.3. 枚举类型的命名一般来说,枚举类型(也称为 enum)的命名应该遵循标准的命名规则(PasacalCasing 大小写风格等等)。但是,还有另外一些针对枚举类型的具体规范。 B. O2-038要用单数名字类命名枚举类型,除非它表示的是位域(bit field) C. O2-039要用复数名词来命名表示位域的枚举类型,这样的枚举类型也称为标记枚举(flag enum)D. O2-040不要给枚举类型的名字添加 “Enum” 后缀 a) 示例下面的命名就不好:public enum ColorEnum A. O2-041不要给枚举类型的名字添加“Flag”或“Flags”后缀a) 示例下面的命名就不好:Flagspublic enum ColorFlags E. O2-042不要给枚举类型值的名字添加前缀(例如,给ADD枚举类型加“ad”前缀,给rich text 枚举类型加“rtf” 前缀)2.6. 类型成员的命名类型由方法、属性、事件、构造函数以及字段等成员组成。下面几节描述了为类型成员命名的规范。 2.6.1. 方法的命名方法是用来执行操作的,框架设计的规范要求方法名必须是动词或动词词组。它还用来把方法同属性和类型名区分开,属性和类型名是名词或形容词词组。 F. O2-044要用动词或动词词组来命名方法a) 示例public class Stringpublic int CompateTo;public string Trim(); 2.6.2. 属性的命名 与其他成员不同,属性应该用名词词组或形容词词组来命名,这是因为属性代表数据,因此它的名字应该反应出这一点,在命名属性时要始终使用PascalCasing 大小写风格。G. O2-045要用名词、名词词组或形容词来命名属性H. O2-046不要让属性名看起来与“Get” 方法的名字相似,如下面的例子所示a) 示例public string TextWriter get. ; set public string GetTextWriter(int value)这中情况一般说明该属性实际上应该是一个方法。 I. O2-047要用肯定行的短语(CanSeek 而不是CantSeek)来命名布尔属性。如果有帮助,还可以有选择性地给布尔属性添加“Is”、“Can”或”Has”等后缀J. A2-006考虑用属性的类型名来命名属性a) 示例下面这个属性的作用是取得和设置一个名为Color的枚举值,因此它被命名为Color: public Enum Color public class Control public Color Colorget ;set 2.6.3. 事件的命名 A. O2-048事件总是表示一些动作,要么是正在发生的,要么是已经发生的。因此,时间和方法一样要用动词来命名,但除此之外,还要用动词的动态来表示事件发生的时间B. O2-049要用现在时和过去时来赋予事件名以之前和之后的概念C. O2-050不要用“Before”或“After”前缀或后缀来区分前置事件和后置事件D. O2-051要在命名事件处理函数(用作事件类型的委托)时加上“EventHandler”后缀E. O2-052要在时间处理函数中用sender 和e作为两个参数的名字a) 解释参数sender表示触发该事件的对象。虽然参数sender可以是一个更为具体的类型,但一般来说起类型就是object。整个.NET框架一致地使用了这个模式。F. O2-053要用动词或动词短语来命名事件G. O2-054要在命名事件的参数类时加上“EventArgs”后缀a) 示例public class ClickedEventArgs: EventArgsint x;int y;public ClickedEventArgs:EventArgs this.x=x;this.y=y;public int xget return x;public int yget return y; 2.6.4. 字段的命名 字段的名称规范适用于静态公有字段和静态受保护字段。这些规范并未涵盖内部字段和私有字段,依据第5章描述的成员设计的规范,实例的公有字段或受保护字段是不允许使用的。H. O2-055要在命名字段时使用PascalCasing大小写风格I. O2-056要用名词或名词短语来命名字段J. O2-057不要给字段名添加前缀a) 示例不要用“g_” 来区分静态和非静态字段。 2.7. 参数的命名 遵循参数的命名规则是很重要的,除了可读性这个显而易见的原因之外,还因为参数会在文档中显示,另外如果可视化的设计工具提供了 Intellisense和类浏览功能的话,那么它们还会在设计工具中显示。K. O2-058要在命名参数时使用camelCasing 大小写风格L. O2-059要使用具有描述性的参数名a) 解释参数名应该具备足够的描述性,使得在大多数情况下,用户根据参数的名字和类型就能够确定它的意思。考虑根据参数的意思而不是参数的类型类命名参数。开发工具必须向用户提供关于类型的有用信息,这样用户就能更好地利用参数名来描述语义,而不是描述类型。偶尔使用基于类型的参数是完全可以的,但在采用这些规范再回到匈牙利命名法则是绝对不应该的。 2.8. 资源的命名 本地化的资源就好比是属性,可以通过特定的对象来引用。因此,资源的命名规范与属性的命名规范相似。M. O2-060要在命名资源关键字时使用PascalCasing大小写风格N. O2-061要使标识符的名字具有描述性而不是使名字变短O. O2-062应该尽可能地使名字简短,但前提是不能牺牲可读性 P. O2-063不要使用各主要CLR编程语言特有的关键字Q. O2-064要在命名资源时仅使用字母、数字和下划线R. O2-065要用点号给标识符清楚地划分层次S. O2-066要在为异常的消息资源命名时遵循西面的命名约定T. O2-067资源标识符应该是异常的类型名加上一个简短的异常标识符,之间以点号分隔a) 解释ArgumentException.IllegalCharactersArgumentException.InvalidNameArgumentException.FileNameIsMalformed 3. 编程风格约定3.1. 通用风格约定3.1.1. 花括号的使用A. 03-001要把左花括号放在下一条语句的开始a) 解释if(someExpression)DoSomething();B. 03-002要使右花括号与左花括号所在行的行首对齐,除非花括号内只有一条语句a) 解释if(someExpression)DoSomething();C. 03-003要把右花括号放在新的一行的开始处a) 示例if(someExpression)DoSomething();D. A3-001考虑把只有一条语句的代码块和左右花括号写在同一行中。属性的访问方法经常使用这种风格a) 示例public int Fooget return foo;setfoo=value; E. A3-002考虑把只有一个访问方法的属性的所有花括号写在同一行中a) 示例public int Foogetreturn f00;F. 03-004要使右花括号单独占一行,除非它后面是else、else if或whilea) 示例if(someExpression)doDoSomething();while(someOtherCondition);G. 03-005避免省略花括号,即使编程语言允许这样做H. 03-006不应该认为花括号是可以省略的,即使对只有一条语句的代码块,仍应该使用花括号I. 03-007只有在极少数情况下才可以省略花括号,比如在原来仅有的一条语句后再添加新的语句是不可能的或是非常罕见的a) 解释本条约定的另一个例外是case语句。由于case和break语句已经表示了代码块的起始和结束,因此这些花括号可以被省略。在throw语句后再添加任何语句都是没有意义的b) 示例If(someExpression) throw new ArgumentOutOfRangeException();Case 0:DoSomething();break; 3.1.2. 空格的使用A. 03-008要在左花括号之后和右花括号之前加一个空格a) 示例public int Foogetreturn f00;B. 03-009避免在左花括号之前加空格a) 示例最好如此:if(someExpression)可以接受;if(someExpression)C. 03-010要在形式参数之间的逗号后加一个空格a) 示例正确:public void Foo(char bar, int x, int y)错误:public void Foo(char bar,int x,int y)D. 03-011避免在实际参数之间加空格a) 示例最好如此:Foo(myChar,0,1)可以接受:Foo(myChar, 0, 1)E. 03-012避免在左圆括号之后或右圆括号之前加空格a) 示例最好如此:Foo(myChar,0,1)可以接受:Foo( myChar,0,1)F. 03-0113不要在成员的名字和左圆括号之间加空格a) 示例正确:Foo()错误:Foo()G. 03-014不要左方括号之后或右方括号之前加空格a) 示例正确:x=dataArrayindex;错误:x=dataArray index ;H. 03-015不要在控制流语句之前加空格a) 示例正确:while(x=y)错误: while (x=y)I. 03-016避免在二元操作符之前和之后加空格a) 示例最好如此:if(x=y)可以接受:if(x =y)J. 03-017不要在一元操作之前或之后加空格。a) 示例正确: if(!y)错误: if(! y)3.1.3. 缩进的使用A. 03-018不要用连续的空格符来进行缩进B. 03-019要用制表符(tab)来进行缩进C. 03-020要对代码块中的内容进行缩进a) 示例if(someExpression)DoSomething();D. 03-021要对case代码块进行缩进,尽管没有使用花括号a) 示例switch(someExpression)case 0:DoSomething();Break; 3.2. 注释规范应该用注释来描述代码的用意、大致的算法以及逻辑流程。最好的情况是,代码编写者之外的人能够通过独自阅读注释来理解函数的行为和目的。虽然注释并不存在一个最低标准,而且一些非常短小的函数根本不需要注释,但对大多数函数来说,通过注释来反映程序员的意图和所采用的方法仍然是值得的。A. 03-022不要用注释来描述一些对任何人都显而易见的事B. 03-023避免使用块注释语法(/*/)。即使注释会有多行,也最好是使用单行注释语法(/)C. 03-024不要把注释放在行尾,除非注释非常短3.2.1. 类属性注释在类的属性必须以以下格式编写属性注释a) 示例在类的属性必须以以下格式编写属性注释:/ / / 3.2.2. 方法注释在类的方法声明前必须以以下格式编写注释a) 示例/ / depiction:/ / param name=/ / 3.3. 文件的组织A. 03-025不要在一个源文件中包含一个以上的公用类型,除非有嵌套类,或各类型之间的不同之处仅在于泛型参数的数量a) 说明一个文件中有多个内部类型是允许的。B. 03-026要用相同的名字来命名源文件及其包含的公用类型a) 解释String类应该在string.cs文件中,而ListT类则应该在List.cs文件中。C. 03-027要用相同的层次结构来组织文件目录和命名空间。a) 解释应该把system.Collections.Generic.ListT的源文件放在SystemCollec-tionsGeneric目录中。D. A3-003考虑根据下面给出的顺序和组别来对成员进行分组l 所有字段。l 所有构造函数。l 公有属性及受保护的属性。l 方法。l 事件。l 所有显式实现的接口成员。l 内部成员。l 私有成员。l 所有嵌套类型。E. 03-028要把不能公开访问的成员和显式实现的接口成员放在分别放在自己的#region块中a) 示例#region internal members#endregion#region private members#endregionF. A3-004考虑在每个组别内根据字母顺序来组织成员G. A3-005考虑根据由简单到复杂的顺序来组织重载成员H. 03-029要把using指令放在命名空间的声明之外a) 示例using Systerm;Namespace System.Collections4. 类型设计规范要确保每个类型由一组定义明确、相互关联的成员组成,而不仅仅是一些无关功能的随机集合。能用简单的一句话来描述一个类型是非常重要的。一个好的定义应该还能去除那些不怎么有关的功能。如果你为了使一个类型对某些人更有用而一下子增加了太多的成员,那么很可能你是在使这个类型对任何人都没有用。4.1. 类型和命名空间在设计一个大型的框架之前,你应该决定如何将功能划分到一组功能域中,这些功能域由命名空间表示。为了确保一组有条理的命名空间包含的类型能很好地集成,不发生冲突,以及不会重复,这样的自顶向下的架构设计是很重要的。当然命名空间的设计过程是迭代的,会随着一个的版本中新类型的加入而进行调整。这导致了下面的规范。A. O4-001要用命名空间把类型组织成一个相关的特性域的层次结构a) 示例该层次结构应该为开发人员更容易地浏览框架并找到想要的API而优化。B. O4-002避免非常深的命名空间层次。这样的层次难于浏览,因为用户不得不经常地回溯C. O4-003避免有太多的命名空间a) 解释在最常见的场景中,框架的用户应该不需要导入许多的命名空间。只要有可该,就应把常见场景中一起使用的类型放在一个单独的命名空间中。D. O4-004避免把为高级场景而设计的类型和为常见编程任务而设计的类型放在同一个命名空间中a) 解释这使得用户不仅更容易地理解框架的基本概念,而且能更容易地在常见的场景中使用框架。E. O4-005不要不指定命名空间就定义类型a) 解释这把相关的类型组织到一个层次结构中,而且有助于解决可能存在的名字冲突。请注意命名空间有助于解决名字冲突的事实并不意味着应该引入这样的冲突。很少使用的类型应该放在子命名空间中,以免搅乱主命名空间。我们确定了几组类型,应该把它们从主命名空间中分离出来。b) 示例System.Windows.Forms.DesignF. O4-006要用带“.Design”后缀的命名空间来容纳那些为基本命名空间提供设计时的功能的类型4.2. 类和结构之间的选择作为一条经验法则,框架中的大多数类型应该是类。但是在有些情况下,由于值类型所具备的特征,使用结构会更为合适。A. A4-001考虑

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论