1.简介
1.1总则
编码规范用于提供统一编码标准,旨在指导源代码文件的规范,以保证开发团队的协作和系统的后期维护能有效进行,编码规范同时作为代码评审的依据。
1.2目的
本规范提供一个C#语言编码的统一标准,目的在于在软件开发过程中基于C#语言的代码能够始终在整个开发团队中保持一致。
1.3适用范围
本规范适用于所有应用C#语言的项目开发与评审活动。
2.格式
2.1缩进
所有的缩进皆为4个空格。对应的括号通常在同一列的位置上。例如:
1)所有的缩进都用"Tab键"形成。
2)所有的if、while和for语句中的语句内容必须用括号括起来,就算只有一个语句。
2.2间隔
所有的标识符都必须被空白字符包围。
例如:
2.3空行
1)在逻辑代码段之间放置空行来分隔代码段;
2)在两个方法/函数/过程之间以空行来分割;
3)在两个类或接口的定义之间放置空行来分隔;
4)命名空间引入完毕之后放置空行。
2.4空格的位置
1)在一个关键字和左括号“(”之间。注意:不要在方法名和左括号之间加空格。
2)在参数列表的每个逗号“,”之后。
3)二元操作符前后。注意:一元操作符前后都不加空格。例如:inta=10;a=a+1;a++;
4)for语句的每个表达式之间。例如:for(inti=0;i20;i++)…。
2.5类成员的摆放顺序
classOrder
{
1.staticfields
2.staticproperties
3.staticmethods
4.staticconstructors
5.fields
6.properties
7.constructors
8.methods
}
9.必须保持private方法被放置在使用该方法的其他方法之上,而在构造器(constr-uctor)之下,即使该构造器有可能调用这些private方法。
2.6文件格式
文件注释必须第一个存在。
接着是命名空间的定义。
在命名空间首先应该using指令
再次,是类型的注释;
示例:
2.7行最大长度
不要让一行代码的长度超过个字符,最好是低于80个字符。如果代码开始向右延伸得很长,你就应该考虑把它分割成更多的方法。
断行规则:
l在逗号的后面;
l在操作符的前面;
l断行的起始位置应该比原行表达式的起始位置缩进4个空格。
2.8括号
使用括号的目的必须是在表达上不但能够标明优先顺序,而且有助于使表达更简单明了。另外,如果某一段代码有可能产生歧义,也需加括号。
3.命名规则
3.1基本原则
除了以下几个特例之外,命名时应始终采用完整的英文描述。此外,一般应采用小写字母,但类名、接口名以及任何非初始单词的第一个字母要大写。
注意:不要将同一变量用作多个用途。(如Dataset类型,每查询一次就要声明一个变量。)
l使用完整的英文描述符;
l采用适用于该领域的术语;
l尽量少用缩写,但如果用了,要明智地使用;
l避免使用长的名字(小于30个字母);
l避免使用类似的名字,或者仅仅是大小写不同的名字;
l避免使用下划线;
3.2大小写
使用下面的三种大写标识符约定:
lPascal大小写:将标识符的首字母和后面连接的每个单词的首字母都大写。可以对三字符或更多字符的标识符使用Pascal大小写。例如:BackColor
lCamel大小写:标识符的首字母小写,而每个后面连接的单词的首字母都大写。例如:backColor
l大写:标识符中的所有字母都大写。仅对于由两个或者更少字母组成的标识符使用该约定。例如:System.IO
下表(表1)汇总了大写规则,并提供了不同类型的标识符的示例。
表2-1
3.3区分大小写
不要使用要求区分大小写的名称。对于区分大小写和不区分大小写的语言,组件都必须完全可以使用。不区分大小写的语言无法区分同一上下文中仅大小写不同的两个名称。因此,在创建的组件或类中必须避免这种情况。
3.4缩写
为了避免混淆和保证跨语言交互操作,请遵循有关区缩写的使用的下列规则:
l不要将缩写或缩略形式用作标识符名称的组成部分。例如,使用GetWindow,而不要使用GetWin。
l不要使用计算机领域中未被普遍接受的缩写。
l在适当的时候,使用众所周知的缩写替换冗长的词组名称。例如,用UI作为UserInterface的缩写,用OLAP作为On-lineAnalyticalProcessing的缩写。
l在使用缩写时,对于超过两个字符长度的缩写请使用Pascalw大小写或Camel大小写。例如,使用htmlButton或HtmlButton。但是,应当大写仅有两个字符的缩写,如,System.IO,而不是System.Io。
l不要在标识符或参数名称中使用缩写。如果必须使用缩写,对于由多于两个字符所组成的缩写请使用Camel大小写,虽然这和单词的标准缩写相冲突。
3.5名字空间的命名
命名名字空间时的一般性规则是使用公司名称,后跟技术名称和可选的功能与设计,如下所示:CompanyName.TechnologyName[.Feature][.Design]
例如:
Microsoft.Media
Microsoft.Media.Design
嵌套的命名空间应当在包含它的命名空间中的类型上有依赖项。例如,System.Web.UI.-Design中的类依赖于System.Web.UI中的类。
应当对命名空间使用Pascal大小写,并用句点分隔逻辑组件,如Microsoft.Office.Power-Point中所示。
3.6类的命名
以下规则概述命名类的规范:
l使用名词或名词短语命名类。
l使用Pascal大小写。
l少用缩写。
l不要使用类型前缀,如在类名称上对类使用C前缀。例如,使用类名称FileStr-eam,而不是CFileStream。
l不要使用下划线字符(_)。
l有时候需要提供以字母I开始的类名称,虽然该类不是接口。只要I是作为类名称组成部分的整个单词的第一个字母,这便是适当的。例如,类名称IdentitySt-ore是适当的。
l在适当的地方,使用复合单词命名派生的类。派生类名称的第二个部分应当是基类的名称。例如,ApplicationException对于从名为Exception的类派生的类是适当的名称,原因是ApplicationException是一种Exception。请在应用该规则时进行合理的判断。例如,Button对于从Control派生的类是适当的名称。尽管按钮是一种控件,但是将Control作为类名称的一部分将使名称不必要地加长。
示例:
publicclassFileStream
3.7接口命名规范
以下规则概述接口的命名规范:
l用名词或名词短语,或者描述行为的形容词命名接口。例如,接口名称IComp-onent使用描述性名词。接口名称ICustomAttributeProvider使用名词短语。名称IPersistable使用形容词。
l使用Pascal大小写。
l少用缩写。
l给接口名称加上字母I前缀,以指示该类型为接口。
l在定义类/接口对(其中类是接口的标准实现)时使用相似的名称。两个名称的区别应该只是接口名称上有字母I前缀。
l不要使用下划线字符(_)。
3.8属性[Attribute]命名指南
应该总是将后缀Attribute添加到自定义属性类。以下是正确命名的属性类的示例。
publicclassObsoleteAttribute{}
3.9枚举类型命名规范
l枚举(Enum)值类型从Enum类继承。以下规则概述枚举的命名指南:
l对于Enum类型和值名称使用Pascal大小写。
l少用缩写。
l不要在Enum类型名称上使用Enum后缀。
l对大多数Enum类型使用单数名称,但是对作为位域的Enum类型使用复数名称。
l总是将FlagsAttribute添加到位域Enum类型。
3.10静态字段命名指南
以下规则概述静态字段的命名指南:
l使用名词、名词短语或者名词的缩写命名静态字段。
l使用Pascal大小写。
l对静态字段名称使用匈牙利语表示法前缀。
l建议尽可能使用静态属性而不是公共静态字段。
3.11参数命名规范
以下规则概述参数的命名指南:
l使用描述性参数名称。参数名称应当具有足够的描述性,以便参数的名称及其类型可用于在大多数情况下确定它的含义。
l对参数名称使用Camel大小写。
l使用描述参数的含义的名称,而不要使用描述参数的类型的名称。开发工具将提供有关参数的类型的有意义的信息。因此,通过描述意义,可以更好地使用参数的名称。少用基于类型的参数名称,仅在适合使用它们的地方使用它们。
l不要使用保留的参数。保留的参数是专用参数,如果需要,可以在未来的版本中公开它们。相反,如果在类库的未来版本中需要更多的数据,请为方法添加新的重载。
l不要给参数名称加匈牙利语类型表示法的前缀。
示例:
TypeGetType(stringtypeName)
3.12控件名称缩写列表
缩写的基本原则是取控件类名各单词的第一个字母,如果只有一个单词,则去掉其中的元音,留下辅音。缩写全部为小写。
3.13方法命名规范
以下规则概述方法的命名指南:
l使用动词或动词短语命名方法。
l使用Pascal大小写。
以下是正确命名的方法的实例。
RemoveAll()
3.14属性命名规范
以下规则概述属性的命名指南:
l使用名词或名词短语命名属性。
l使用Pascal大小写。
l不要使用匈牙利语表示法。
l考虑用与属性的基础类型相同的名称创建属性。
3.15事件命名指南
以下规则概述事件的命名指南:
l对事件处理程序名称使用EventHandler后缀。
l指定两个名为sender和e的参数。sender参数表示引发事件的对象。sender参数始终是object类型的,即使在可以使用更为特定的类型时也如此。与事件相关联的状态封装在名为e的事件类的实例中。对e参数类型使用适当而特定的事件类。
l用EventArgs后缀命名事件参数类。
l考虑用动词命名事件。
l使用动名词(动词的“ing”形式)创建表示事件前的概念的事件名称,用过去式表示事件后。例如,可以取消的Close事件应当具有Closing事件和Closed事件。不要使用BeforeXxx/AfterXxx命名模式。
l不要在类型的事件声明上使用前缀或者后缀。例如,使用Close,而不要使用 OnClose。
l通常情况下,对于可以在派生类中重写的事件,应在类型上提供一个受保护的方法(称为OnXxx)。此方法只应具有事件参数e,因为发送方总是类型的实例。
4.注释
为增加程序的可读性,编写的代码应加上注释,注释的原则为:
l避免使用装饰物;
l保持注释的简洁;
l在写代码之前写注释;
l注释出为什么做了一些事,而不仅仅是做了什么;
c#语言提供了3种形式的注释:
//text从//到本行结束的所有字符均作为注释而被编译器忽略。
/*text*/从/*到*/间的所有字符会被编译器忽略。
表3-1
可以轻松地在C#代码结构中添加文档注释,并通过代码注释Web报告进行查看。显示在代码注释Web报告中的注释和XML标记以注释语法///开头。通常,文档注释注释在用户定义的类型(如类、结构或接口)、成员(如字段、事件、属性或方法)或命名空间声明之前输入。
例如:
在C#代码中添加文档注释:
在编辑器中打开.cs文件。
切换到代码视图。
输入///,后面可跟任何XML标记或文本字符串。如果在定义之前的行上输入///,则编辑器将创建文档注释模板并填入参数和其他信息。
例如,文件class1.cs中,在publicClass1()前可输入下列信息:
在Class1的代码结构中,summary/summary标记中所列出的信息出现在“说明”列。remarks/remarks标记中所列出的信息出现在备注部分的class1详细信息页中。
5.编码
一种提高代码可读性的方法是给代码分段,在代码块内让代码缩进。所有在括号{和}之内的代码,构成一个块。基本思想是,块内的代码都应统一地缩进去一个单位。
c#的约定:开括号放在块的所有者所在行的下面并缩进一级,闭括号也应缩进一级。
在代码中使用空白。将代码分为一些小的、容易理解的部分,可以使它更加可读。建议采用一个空行来分隔代码的逻辑组,例如控制结构,采用两个空行来分隔成员函数定义。
遵循30秒条法则。其他的程序员应能在少于30秒钟的时间内完全理解你的成员函数,理解它做什么,为什么这样做,它是怎样做的。一个好的经验法则是:如果一个成员函数一个屏幕装不下,那么它就很可能太长了。
写短小单独的命令行。每一行代码只做一件事情。应使代码尽量容易理解,从而更容易维护和改进。正如同一个成员函数应该并且只能做一件事一样,一行代码也只应做一件事情。
应让代码在一个屏幕内可见。也不应向右滚动编辑窗口来读取一整行代码,包括含有行内注释语句的代码。
6.不要使用的结构
6.1“do…while”
不要用do…while循环,用while()循环。
6.2“return”
不要在一个方法的中间使用“return”,“return”只能出现在一个方法的末尾。
原因:在方法的中间使用“return”会给重构(今后将方法拆分成几个更小的方法)带来困难;而且它会迫使开发者不得不为该方法考虑多于一个的出口点。
6.3“continue”
绝不要用“continue”。
原因:“continue”会给将来把一个结构拆分成几个更小的结构或方法带来许多困难;而且她也会迫使开发者不得不为该结构考虑多于一个的结束点。
6.4“break”
“break”只能用于转换状态(switchstatement)的控制。
原因:在转换状态控制之外的情况下使用break,会给将来把一个结构拆分成几个更小的结构或方法带来许多困难;而且她也会迫使开发者不得不为该结构考虑多于一个的结束点。
7.不要混合使用递增运算符和递减运算符
不要混合使用递增运算符和递减运算符,
原因:在方法调用或是数学运算中混合使用递增运算符(或递减运算符)会造成欠经验的程序员阅读的困难。
所以,最好在递增运算符(或递减运算符)之间加上额外的行。
变量初始化
最好总是在每个变量声明的时候就马上进行初始化。
最好只在需要的时候再声明(declare)一个变量,不然的话会影响代码的执行效果。
示例:
8.不要使用数字/字符
程序中应尽可能少使用数字/字符,尽可能定义静态变量来说明该数字/字符的含义,程序中需要赋值或比较时,使用前面定义的静态变量。
例如:date1.get(1),而应该date1.get(MyDate.YEAR)。
例外:
循环控制:例如:
9.重复代码块
尽量避免使用重复的代码块,如果一个类中出现2个以上相同功能的代码块,应该将它作为类的私有方法;如果你认为多个类中都可以用到,应该将它作为util中的方法,并通知做工具类的人去写这个方法。
10.范围
原则上类的成员变量必须是总是private,尽量少用protected和public,但以下情况例外:
l内部类的成员变量(可以为public);
l子类可继承的基类成员变量(可以为protected);
l并发控制中的信号变量(可以为public)。
11.异常处理
每个页面加上排除异常代码,保证程序在发生异常后能继续正常运行,采用try、catch、finally结构,如:
说明:Try…Catch…finally异常处理模式是很消耗资源的,所以所加位置要慎重,避免多余的异常处理。