C#代码规范范本.docx
《C#代码规范范本.docx》由会员分享,可在线阅读,更多相关《C#代码规范范本.docx(21页珍藏版)》请在冰豆网上搜索。
C#代码规范范本
C#编码规范
目录方针
该代码标准提供了相关软件开发项目中,使用C#进行编码时的规则,推荐代码标准,起到了一定的指示作用。
为了使该标准制定的方针浅显易懂,用了简单的代码来编写。
而在实际的编程中,是需要项目小组所有成员同意该编写规则的。
对于实际项目,我们推荐将该标准以顾客为标准使用。
还有,我们还推荐读者参考配合.NETFrameworkSDK帮助的《面向对象开发设计指南》。
※特别是在ExtremeProgramming项目中没有认识到的,可使用其它C#编程的项目中运用。
1.代码注释规范
(1)文件功能,创建,修改信息注释
(2)类功能注释
(3)方法注释
(4)较长的注释,*GY
需要复数行注释的情况下,在最初用短小的篇章写上想要注释什么。
然后在添加上长的注释。
另外,在感觉有必要写象如此长的注释之时,请再三考虑一下,可否将程序设计再简化一下。
请积极地应对。
2.目录文件构成
(5)目录文件名
Public类会生成一个以该类命名的文件。
例:
publicclassCustomer里面有着Customer.cs。
包内的非公共类,最好放在包含该类经常被使用的公共类目录文件下。
对于特殊类,一个目录文件可以包含多个类。
(6)目录文件的位置
决定了项目的根目录之后,在命名空间的“.”处输入导入目录的阶层位置。
可是对应于solution/project的命名空间的阶层则用solution名/project名作为目录名来使用。
例:
命名空间:
CompanyName.OrganizationName.TechnologyName.CoreFeatureName.SubFeatureName
SolutionSolutionName所对应的命名空间:
TechnologyName
ProjectProjectName所对应的命名空间:
CoreFeatureName
配置路径:
C:
\CompanyName\OrganizationName\SolutionName\ProjectName\SubFeatureName
(7)TestClass名
类ClassName的单元测试类是以ClassNameTest来命名的。
Solution的每个测试都是以SolutionNameTests来命名的。
例:
如果是Customer类的测试类的话就命名为CustomerTest.cs。
例:
如果是CsSample的soultion的话,就把它命名为CsSampleTests.csproj。
理由:
因为是这样命名是非常有一致性。
可以成为使用测试代码的样例和演示版。
(8)TestClass的位置
测试类的位置应配置在被测试类相同的阶层的目录下。
例:
被测试类的位置:
测试类的位置:
理由:
如果不是物理位置较近的话,会被维护系统所遗漏。
对于产品的代码分离这一点而言,用其他的工具(NAnt的build文件之类)也是可能调整的。
3.命名规则
(9)NameSpace结构规范
NameSpace分类和命名原则
先根据解决方案(Solution)、业务系统(Application)、子系统(Sub)、模块(Module)划分目录,然后在模块内部按照Web、Biz、integration层对NameSpace结构进行命名。
Web层NameSpace命名规范
●Beyondbit.Solution.Application.Sub.Module.Web
业务层NameSpace命名规范
●Beyondbit.Solution.Application.Sub.Module.Biz
数据访问层NameSpace命名规范
●Beyondbit.Solution.Application.Sub.Data
集成层NameSpace命名规范
●Beyondbit.Solution.Application.Sub.Module.Biz
Common
该目录应用于解决方案(Solution)、业务系统(application)、子系统(sub),存放在一些与业务相关的通用处理程序,可以视为公共的模块,可包含Web、Biz、integration。
Util
该目录应用于解决方案(Solution)、业务系统(Application)、子系统(Sub),存放在一些与业务无关的通用处理程序。
(10)文件名
Public类的命名一定要与文件名同名(包括大,小写的区别)。
(11)类名
类名使用Pascal大小写形式。
(12)异常类名
最后以Exception结尾。
(13)接口名
与类名相同。
此外,经常在最前面添加I。
interfaceIClassName
此外,在使用添加了某项功能的情况下,我们要加上可以表示这种功能的形容词,以-able结尾。
例:
IEnumerable,ICloneable,IXmlSerializable,…
(14)抽象类名
如果没有适合抽象类名的名字的时候,就联想以Abstract为开头的Subclass名作为抽象类的名字。
abstractclassAbstractBeforeSubClassName
(15)常量(Const)
用大写或者大写后加“_”。
constintUPPERCASE=0;
constintUPPERCASE_WITH_UNDERSCORES=0;
(16)枚举型(enum)
枚举名使用Pascal大小写格式。
enumPascalCasing
枚举型在表示位域的时候用复数。
并附加FlagsAttribute。
[Flags]enumPascalCasings
(17)枚举值
枚举值使用Pascal大小写格式。
PascalCasing
(18)事件名
事件名使用Pascal大小写格式。
eventPascalCasing()
(19)方法名
方法名使用Pascal大小写格式。
voidPascalCasing()
objectPascalCasing()
(20)factory方法(生成新的对象)
XNewX()
XCreateX()
(21)转换方法(把一个对象转换成别的对象)
XToX()
(22)属性名
属性名使用Pascal大小写形式。
objectPascalCasing
(23)Boolean变量返回方法
Is+形容词、Can+动词、Has+过去分词、三单元名词、三单元动词+名詞。
好的例子:
boolIsEmpty()
boolCanGet()
boolHasChanged()
boolContains(objectx)
boolContainsKey(stringkey)
boolCheckUserRight(stringuserId,stringrightId)
不好的例子:
boolEmpty()//方法调用者会理解成“清空”的意思。
理由:
方法调用者很容易理解if,while等条件语句的条件。
另外,也很容易理解ture意味着什么。
(24)Bool变量
形容词、is+形容词、can+动词、has+过去分词、三单元动词、三单元动词+名词。
形容詞、is+形容詞、can+動詞、has+過去分詞、三単元動詞、三単元動詞+名詞。
boolisEmpty;
booldirty;
boolcontainsMoreElements;
(25)英语和中文
所有的关键词名都是以英语为基础,另外,在整个项目的制作周期中都有中英对照字典的支持。
(26)命名的对称性
要取类名,方法名的时候请注意以下的英语的对称性。
Add/Remove
Insert/Delete
Get/Set
Start/Stop
Begin/End
Send/Receive
First/Last
Get/Release
Put/Get
Up/Down
Show/Hide
Source/Target
Open/Close
Source/Destination
Increment/Decrement
Lock/Unlock
Old/New
Next/Previous
(27)循环计数器
对于应用Scope(适用范围)的局部循环计数器,以i,j,k为顺序依次命名。
(28)Scope的局部变量命名
Scope的局部变量名最好使用其类型名的缩写。
例:
DataSetds=newDataSet();
(29)有意义的命名
最好使用从名字中就可以看出其变量作用的变量名。
不好的例子:
Copy(strings1,strings2)
好的例子:
Copy(stringsource,stringdestination)
(30)无意义的命名
用Info,Data,Temp,Str,Buf这些做变量名的时候需要再三考虑。
不好的例子:
doubletemp=Math.Sqrt(b*b-4*a*c);
好的例子:
doubledeterminant=Math.Sqrt(b*b-4*a*c);
(31)private/protected/internal/protectedinternalscope的实例变量
使用Camel大小写形式。
我们需要考虑的是使变量更加容易读懂。
privateobjectcamelCasing;
protectedobjectcamelCasing;
internalobjectcamelCasing;
protectedinternalobjectcamelCasing;
(32)publicscope的实例变量
使用Pascal大小写形式。
开头用大写。
publicobjectPascalCasing;
(33)private/protected/internal/protectedinternalscoope的公共变量
使用Camel大小写形式。
我们要考虑使得变量更加容易读懂。
privatestaticobjectcamelCasing;
protectedstaticobjectcamelCasing;
internalstaticobjectcamelCasing;
protectedinternalstaticobjectcamelCasing;
(34)publicscope的公共变量
使用Pascal大小写形式。
publicstaticobjectPascalCasing;
(35)Local变量
使用Camel大小写形式。
objectcamelCasing;
(36)大写与小写
大写与小写被作为不同的文字被使用。
仅仅因为这个区别我们就不得不注意名字的取法。
4.代码编写
(37)#Region/#EndRegiondirective
代码域要声明#Region/#EndRegiondirective,要包含这个域相关的说明。
例:
#Region"实例变量"
privatestringname;
#EndRegion
#Region"Constract"
publicMyClass(stringname)
{
this.name=name;
}
#EndRegion
(38)声明方法/属性
声明方法/属性要明确指出scope。
(39)较长的行
一行最多100位,如果有超过的情况要分割行。
分行指针通过逗号另起一行。
例:
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0)+Math.Pow(newRandom().NextDouble(),2.0));
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0),
Math.Pow(newRandom().NextDouble(),2.0));
(40)较长的类的声明
类声明较长的情况下,请换成多行。
例:
publicclassLongNameClassImplemenation:
AbstractImplementation,IXmlSerializable,Icloneable
那么请变为:
publicclassLongNameClassImplemenation:
AbstractImplementation,
IXmlSerializable,ICloneable
(41)较长的方法声明
方法声明较长的情况下,请换成多行。
例:
publicvoidLongMethodSignature(inta,intb,intc,
intd,inte,intf)
(42)abstractClassvs.interface
请尽量不要使用抽象类(abstractclass),多使用interface。
abstractclass是有体方法与抽象方法的结合使用。
理由:
一个类可以实现很多接口,却只能继承一个抽象类。
一个类继承之抽象类后就不能继承其他的类,会造成浪费。
(43)publicVariable
类变量请不要频繁将其设为public的作用域,请将它设置为合适的作用域。
理由:
这是面向对象的标准。
随意地访问类的内部状态是不好的。
可是,在满足以下全部条件时,类的public变量可以直接访问。
●该类变量独立于其他的类变量,单独变更其内容的话,是不会对内部的整合性造成影响的。
●无论哪个,都要编写上get/set访问。
●有证据说明类变量在实例化后不会变更。
另外,遇到不适合上述情况的时候,如需要极度注重开发速度的情况。
也不仅限于上述的标准。
(可是,需要我们慎重地注释)
(44)初始化
不要指望默认的初始化(比如将某些变量用null值初始化之类)。
另外,不要再次初始化。
不好的例子:
publicclassPoorInitialization
{
privatestringname="initial_name";
publicPoorInitialization()
{
name="initial_name";
}
}
理由:
请把关于初始化的Bug减到最低。
(45)避免static变量
请尽力避免static变量。
理由:
它使用了更加使上下文连贯的代码,覆盖隐藏了副作用。
(46)privatevs.protected
比起private,我们应更多使用protected。
理由:
private不让该类以外的其他类调用。
客户无法对继承此类的private的方法重新实现。
别的方法:
请选private使用。
如果将属性变为protected之后,如果该类有变更的话,那么对全部继承它的类都会有影响。
(47)get/set访问
请避免随便地将实例变量的作用域(get/set访问)定为public的作用域。
在这之前请讨论其必要性,将它做成更加有意义的属性/方法。
理由:
类变量经常依赖其他类变量。
我们不能破坏类内部的整合性。
(48)隐藏变量
隐藏变量名请避免和基本类中的变量名同名。
理由:
一般来说,会产生Bug。
如果有特殊意义的话请注释一下。
(49)Public方法
类的public方法是以“自动贩卖机的界面”为目标,为了变得浅显易懂,即使使用方法错误,也不会破坏其内部整合性而设计的。
另外,如果可能的话,请根据协议而设计(DesignbyContract),与类的不变条件一起,用代码表现方法的重载。
(50)获得状态与变更状态的分离
请将方法设计为执行“一种功能”。
特别是,变更状态和获得状态这两种服务不能在一个方法内执行。
请用void做为状态变更方法的返回值。
理由1:
只执行一件事情的方法比较容易理解。
理由2:
比较容易做到对于并发性的控制,异常的安全保证。
理由3:
根据子类化比较容易扩展。
(51)this的返回
就算是为了客户的方便着想,也请尽量避免this的返回。
理由:
像A.Meth1().Meth2().Meth3()这样的连锁,一般会变成Synchronization上问题的根源。
(52)方法的多重定义
根据参数的类型不同,请尽量避免方法的重载(如果参数不相同的话是可以)。
特别是,如果和继承挂钩的话会很麻烦。
例:
错误:
overridevoidDraw(Rectanglerectangle)
overridevoidDraw(Pointpoint)
正确:
voidDrawRectangle(Rectanglerectangle)
voidDrawPoint(Pointpoint)
(53)Equals()与GetHashCode()
如果要重载Object.Equals()方法的话,请同时重载GetHashCode()方法。
相反也一样。
理由:
为了对应容器类(Hashtable)
(54)Clone()
如果,使用了Clone()方法的话,实际装载ICloneable明确地书写。
。
例:
usingSystem;
publicclassFoo:
ICloneable
{
publicobjectICloneable.Clone()
{
FoomyFoo=(Foo)this.Clone();
//Foo类属性的clone
//...
}
}
理由:
有许多例子表明简易的复制是不好的。
(55)deflautconstract
如果可能的话,请都准备使用一个deflautconstract(哪怕是没有参数)。
理由:
使用reflection,用Assembly.CreateInstance(TypeName)从类型名字符串开始做成该动态类。
(56)abstractMethodinabstractclasses
对于abstract类来说,比起书写no-op的方法来,请明确地声明成abstract方法。
另外,如果可以准备好可能共享的default的实现的话,将其设为protected属性,请在子类中用一行书写处理方法。
理由:
.NET的IDE并没有实际实现。
为了检测出abstract方法,可以回避仅仅忘记实际实现IDE的BUG。
(57)类型的变换
类型的变换请使用Convert类。
stringstr="123456789";
intnum=Convert.ToInt32(str);
intnum=123456789;
stringstr=Convert.ToString(num);
(58)对象的同值比较
对象比较==使用方法,不使用Equals。
String的比较就使用==来比较。
。
另外,比较独立对象的情况下,请按照如下的方式来实现独立对象:
Equals,GetHashCode,operator==,operator!
=
理由:
如果使用Equals方法的话,源代码就会看上去比较混乱。
classHoge
{
privatestrings;
publicHoge(strings)
{
this.s=s;
}
publicoverrideboolEquals(Objecta)
{
returnEquals(this.s,((Hoge)a).s);
}
publicstaticbooloperator==(Hogea,Hogeb)
{
returnEquals(a.s,b.s);
}
publicstaticbooloperator!
=(Hogea,Hogeb)
{
return!
Equals(a.s,b.s);
}
publicoverrideintGetHashCode()
{
returns.GetHashCode();
}
}
(59)声明与初始化
Local变量请和初始值一起声明。
理由:
请最小化关于变量值的设定。
不好的例子:
voidf(intstart)
{
inti,j;//没有声明初始值
//许多代码
//...
i=start+1;
j=i+1;
//使用了i,j
//...
}
好的例子:
voidf(intstart)
{
//许多代码
//...
inti=start+1;
intj=i+1;
//使用了i,j
//...
}
(60)Local变量重复使用的坏处
如果重复使用Local变量,应该声明新的变量并初始化。
理由:
关于变量值的假定应该最小化。
理由:
对编译的优化有帮助。
不好的例子:
voidf(intn,intdelta)
{
inti;//没有初始化的声明
for(i=0;i{
//使用了i
}
for(i=0;i{
if(...)
{
break;
}
}
if(i!
=n-1)//循环终止判定条件里面使用了i
{
//...
}
i=n-delta*2;//再次使用了i
//...
}
好的例子:
voidf(intn,intdelta)
{
for(inti=0;i{
//使用了i
}
boolfound=false;
for(intj=0;i{
//使用了j
if(...)
{
found=true;
break;
}
}
if(found)
{
//...
}
inttotal=n-delta*2;//有着其他意思的变量
//...
}
(61)大小比较运算符
比较习惯使用“<”、“<=”,而“>”、“>=”请尽量避免。
理由:
为了统一字符大小的方向,右边的字符大的话,可以避免混乱。
(62)If/while条件中的“=”
对于if,while的条件,不可以代入“=”使用。
理由:
几乎在所有这