第1页共69页最后更新:2010-09-091.前言1.1.目的本文档用于规范.NET代码编写工作。任何代码编写工作都需按照此规范执行。1.2.约定在每小节下面都有一些要求必须遵守,或者建议遵守的规范。通过O(Obey)表示必须遵守,A(advise)表示建议遵守。[O2--001]XXX。表示第一章第一个必须遵守的规范。[A2-001]XXX。表示第一章第一个建议遵守的规范。1.3.参考资料编号资料名称简介作者日期出版单位001FrameworkDesignGuidelines:Conventions,Idioms,andPatternsforReusable.NETLbraries框架设计师和开发人员的权威指南。KrzyszofCwalinaBradAbrams2006年7月MicrosoftCorporation002CodeCompleteSteve、McConnell2006年MicrosoftCorporation1.4.术语序号术语备注1234第2页共69页最后更新:2010-09-095678910第3页共69页最后更新:2010-09-092.命名规范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)示例第4页共69页最后更新:2010-09-09不要使用CDocument来定义文档类,而是使用Document。E.[O2-005]不要使用与广泛使用的编程语言的关键字有冲突的标识符。a)解释根据CLS(公共语言规范)的第4条规则,所有符合规范等语言必须提供一种机制,允许用户访问以该语言的关键字来命名的标识符。例如,C#在这种情况下使用@符号作为转义机制(escapemechanism)。但是,由于在使用方法时,用转义序列(escapesequence)要比不用转义序列麻烦得多,因此避免使用常见的关键字仍然是个好习惯。b)示例不要定义一个Type@class;的变量来表示类型,而应该用Typetype;2.1.2.使用单词缩写和首字母缩写词A.[O2-006]不要使用缩写词和缩约词作为标识符名字的一部分a)解释一般来说,不要在标识符中使用单词缩写或首字母缩写词。正如前面所讲,对名字来说,可读性比简短更重要。另外有一点也同样重要,即不要使用未被广泛接受的单词缩写和首字母缩写词,也就是说,大多数非领域专家的人能够立刻知道它们是什么意思。b)示例要用GetWindow,而不要用GetWin。B.[O2-007]不要使用未被广泛接受的首字母缩写词,即使是被广泛接受的首字母缩写词,也应该在必须的时候才使用a)解释例如,UI用来表示UserInterface,HTML用来表示HypertextMarkupLanguage。在框架的标识中使用它们仍是不好的做法。2.1.3.避免使用语言特有的名字对那些所谓的基本类型,CLR平台上的编程语言通常都有自己的名字(别名)来称呼它们。例如,int是C#中System.Int32的别名。为了确保框架能够充分利用跨语言协作---CLR的核心特性之一,避免在标识中使用语言特有的类型名是很重要的。第5页共69页最后更新:2010-09-09A.[O2-008]要给类型名使用语义上有意义的名字,而不要使用语言特有的关键字b)示例例如:GetLength这个名字比GetInt要好。B.[O2-009]要使用CLR的通用类型名,而不要使用语言特有的别名--如果除了类型之外,标识符没有其他的语义a)示例一个把类型转换为System.Int64的方法应该被命名为ToInt64,而不是Toloong(因为System.Int64是CLR类型名,它对应于C#特有的别名long)。表3-3列出了有别名的基本类型在CLR中的类型名(以及与C#、VisualBasic、C++相对应的类型名)。C.[O2-010]要使用常见的名字,比如value或item,而不要重复类型的名字---如果除了类型之外,标识符没有其他的语义,而且参数的类型不重要a)示例类提供的这些方法可以把各种不同的数据类型写入流中:voidWrite(doublevalue);voidWrite(floatvalue);voidWrite(shortvalue);2.1.4.为已有API的新版本命名有时无法将一个新特征添加到一个已有的类型中去,即使已有类型的名字意味着它是新特征的最佳归宿。在这种情况下需要添加一个新类型,但由于要给新类型找一个好的新名字,因此这通常给框架设计师出了难题。类似地,在需要提供额外的功能时,经常会无法对已有的成员进行扩展或重载,为此,只能用新名字来添加新成员。下面的规范描述了当用新类型和新成员接替或取代已有的类型或成员时,如何为它们选择名字。A.[O2-011]要在创建已有API的新版本使用与旧API相似的名字。这有助于突出API之间的关系a)示例classAppDomain{[Obsolete(“AppDoMain.SetCachePathhasbeendeprecated”)]publicvoidSetCachePath(Stringpsth){..…}}第6页共69页最后更新:2010-09-09classAppDomainSetup{publicstringCachePath{get{…};set{…};}}B.[O2-012]要优先使用后缀而不是前缀来表示已有API的新版本。这有助于在浏览文档或使用Intellisense时发现新版本。由于大多数浏览器和Intellisense按字母的顺序显示标识符,因此旧API与新API在位置上会非常接近C.[A2-001]考虑使用全新但有意义的标志符号,而不是简单地给已有标识符添加后缀或前缀。D.[O2-013]要使用数字后缀来表示已有API的新版本,如果已有API的名字是唯一有意义的名字(也就是说,它是一个工业标准),不适宜添加后缀(或改名)E.[O2-014]不要在标识符中使用“Ex”(或类似的)后缀来区分相同API的不同版本。a)示例publicclassCarEx{…}//thewrongwayF.[O2-015]要在引入对64位整数(long)而非32位整数进行操作的新版本API时使用“64”后缀。只有当已经存在32位的API时才需要采用这种方法,对只有64位版本的全新API则不需要这要做2.2.大小写约定因为CLR支持许多编程语言,这些语言有的区分大小写,有的不区分,所以不应该只用大小写来区分名字。但是,大小写对增强名字可读性的重要性怎么强调也不过分。本章中的规范展示了一种使用大小写的简单方法,如果一致地使用,那么会使类型、成员以及参数的标识符更易于阅读。2.2.1.标识符的大小写规则为了区分一个标识符中的多个单词,把标识符中的每个单词的首字母大写。不要用下划线来区分单词,或者在标识符中的任何地方使用下划线。有两种合适的方法来大写标识符中的字母,这取决于所使用的标识符:第7页共69页最后更新:2010-09-09PascalCasingcalmelCasingPascalCasing约定被用于除了参数名、变量名、私有字段名之外的所有标识符,它把标识符中每个单词的首字母(包括长度为两个字符以上的首字母缩写词)大写,如下面的例子所示:HtmlTag两个字母长的首字母缩写词是一个特例,在这种情况下两个字母都要大写,如下面的标识符所示:IOStreamcamelCasing约定用于参数、变量、私有字段的名字,它把标识符中除了第一个单词之外的所有单词的首字母大写,如下面的例子所示。在例子中,如果camolCasing风格的标识符以两个字母长的首字母,那么两个字母都要小写。ioStreomhtmlTagA.[O2-016]要把PascalCasing用于由多个单词构成的名字空问、类型以及成员的名字a)示例使用Textcolor而不是Textcolor或Text_color。单个单词(比如Button)直接首字母大写。始终作为一个单词的复合词(比如endpoint)视为一个单词,只有第一个字母大写。B.[O2-017]要把camelCasing用于参数的名字b)示例表2-1不同类型的标识符的大小写规则----------------------------------------------------------标识符大小写样例----------------------------------------------------------命名空间:PascalnamespaceSystem.Security{….}类型:第8页共69页最后更新:2010-09-09PascalpublicclassStreamReader{…}接口:PascalpublicclassStreamReader{…}方法:PascalpublicclassObject{publicvirtualstringToString();}属性:PascalpublicclassString{publicintLength{get;}}事件PascalpublicclassProcess{publiceventEventHandlerExited;}字段(静态)PascalpublicMessageQueue{publicstaticreadonlyTimeSpanInfiniteTimeout;}枚举值PascalFileMode{Append,…}参数CamelpublicclassConvert{publicstaticintToInt32(stringvalue);}-------------------------------------------------------------------第9页共69页最后更新:2010-09-092.2.2.首字母缩写词的大小写一般来说,避免在标识符的名字中使用首字母缩写词是很重要的,除非它们是普遍使用的,能够立刻使用框架的人所理解。例如,HTML、XML和IO很容易理解,但不怎么常用的首字母缩写词绝对应该避免。2.3.程序集和DLL的命名程序集是一个部署单元,同时还代表托管代码程序的身份。虽然程序集可以分布在一个或多个文件中,但一般来说一个程序集仅与一个DLL想对应。因此,本节只讨论DLL的命名约定,程序集的命名约定与次类似。命名空间与DLL和程序集是不同的概念。命名空间对开发人员来说是一组逻辑实体,而DLL和程序集则是在打包和部署时的一个单元。DLL可以因产品的组织及其他原因而包含多个命名空间。由于命名空间的组织方法与DLL不同,因此应该单独设计。例如,如果决定把DLL命名为MyConpany.MyTechnology,这并不意味着DLL必须包含名为MyCompany.MyTechnology的命名空间。