CodingStdCStreC#编程规范烟台创迹软件.docx
- 文档编号:24050865
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:31
- 大小:117.67KB
CodingStdCStreC#编程规范烟台创迹软件.docx
《CodingStdCStreC#编程规范烟台创迹软件.docx》由会员分享,可在线阅读,更多相关《CodingStdCStreC#编程规范烟台创迹软件.docx(31页珍藏版)》请在冰豆网上搜索。
CodingStdCStreC#编程规范烟台创迹软件
C#编程规范
烟台创迹软件——C#编程规范2006年11月3日最新版
1.方针
这份规范的制定方针是,对写出易读的代码提供支持。
在实际的编码中,为使所有的C#项目开发成员依据该标准编写出易读性强的代码。
请大家认真阅读,遵守此规范。
2.文件构成
(1)文件名
对于Public类,以它的类名做成一个文件。
例:
把publicclassCustomer放入Customer.cs类文件里面。
封装内的非公共类,可以包含在那个主要被使用的公共类的文件里。
异常处理类,多个处理类可以放在一个文件里。
(2)文件的位置
在确定了项目的根目录后,在各个目录层次连接的地方放入命名空间的“.”。
但是,对应于solution/project命名空间的层次,在目录里使用solution名/project名。
例:
命名空间:
CompanyName.OrganizationName.TechnologyName.CoreFeatureName.SubFeatureName
对应于solutionSolutionName的命名空间:
TechnologyName
对应于项目ProjectName的命名空间:
CoreFeatureName
上述命名空间所对应的代码存放的路径:
C:
\CompanyName\OrganizationName\SolutionName\ProjectName\SubFeatureName
(3)测试类名
类ClassName的单元测试类名为ClassNameTest。
Solution的单元测试的名称命名为SolutionNameTests。
例:
类Customer作成测试类CustomerTest.cs
例:
SolutionCsSample作成CsSampleTests.csproj
理由:
可以保持命名的一致性。
测试代码可以成为使用方法的样本和现成的例子。
(4)测试类的位置
在和被测试类相同层次的目录及子目录里,配置测试类的位置。
例:
被测试类的位置:
C:
\CompanyName\OrganizationName\SolutionName\ProjectName
测试类的位置:
C:
\CompanyName\OrganizationName\SolutionName\SolutionNameTests
C:
\CompanyName\OrganizationName\SolutionName\SolutionNameTests\ProjectNameTests
理由:
如果不放在物理位置相近的地方,很容易忘掉。
至于和成品代码分离的时候,使用其他工具(NAnt的build文件等)可能会有所调整。
3.命名规则
(5)命名空间
使用“公司名.组织名.技术名.功能名”的形式。
另外,技术名和Solution名、功能名和项目(Project)名要一一对应。
usingCompanyName.OrganizationName.TechnologyName.FeatureName
(6)文件名
公共类名和文件名必须相同。
(区分大小写)
(7)类名
开头是大写。
以后的单词首字母大写。
classPascalCasing
(8)异常处理类的类名
在类名最后加上Exception。
classClassNameEndsWithException
(9)接口名
与类名的命名方法相同。
经常在开头添加“I”。
interfaceINameOfInterface
另外,在类里面使用到的功能,也加到名字里。
功能用形容词来表示,用-able结尾。
例:
IEnumerable,ICloneable,IXmlSerializable,…
(10)密封类名
要和Interface进行必要的区别,在末尾添加“Impl”。
classClassNameEndsWithImpl
(11)抽象类名
在没有恰当的名字来表示抽象类时,以Abstract开头,在其后跟上可以联想到的子类的名字。
abstractclassAbstractBeforeSubClassName
(12)常量(Const)
用大写字母或者是用下划线“_”连接大写字母来命名。
constintUPPERCASE=0;
constintUPPERCASE_WITH_UNDERSCORES=0;
(13)枚举型(enum)
开头大写,其后单词首字母大写。
enumPascalCasing
用枚举型表示多个BitField时,加上FlagsAttribute。
[Flags]enumPascalCasings
(14)枚举值
开头大写,其后单词首字母大写。
PascalCasing
(15)事件(Event)名
开头大写,其后单词首字母大写。
eventPascalCasing()
(16)方法(Method)名
开头大写,其后单词首字母大写。
voidPascalCasing()
objectPascalCasing()
(17)Factory方法(新建对象)
XNewX()
XCreateX()
(18)Convert方法(转换对象)
XToX()
(19)属性名
开头大写,其后单词首字母大写。
objectPascalCasing()
(20)返回Boolean变量的方法
Is+形容词、Can+动词、Has+过去分词、动词第三人称单数、动词第三人称单数+名词。
好的例子:
boolIsEmpty()
boolCanGet()
boolHasChanged()
boolContains(objectx)
boolContainsKey(stringkey)
不好的例子:
boolEmpty()//可以理解为“对空进行操作”的动词性意思。
boolCheckXXX()//难以判断true代表的含义。
理由:
使if,while语句的条件易读,并且true代表的意思容易理解。
(21)Bool变量
形容词、Is+形容词、Can+动词、Has+过去分词、动词第三人称单数、动词第三人称单数+名词。
boolisEmpty;
booldirty;
boolcontainsMoreElements;
(22)英语和日语
基本上所有关键字的名字都是英语,另外,在项目的整个生命周期内,可以做成日英对照词典。
(23)名称的对称性
在命名类和方法时,请留意以下的英语的对称性。
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
(24)循环计数器(LoopCounter)
当作用域(通用范围)很小时,循环计数器就可以顺序地使用i,j,k等名字。
(25)小作用域的变量命名
当变量名的作用域很小时,可以使用类型名称的缩写。
例:
DataSetds=newDataSet();
(26)名称要能表达变量的意思。
通过变量名就能明白变量的作用。
不好的例子:
Copy(strings1,strings2)
好的例子:
Copy(stringsource,stringdestination)
(27)没有实际意思的名字
对于Info,Data,Temp,Str,Buf等这些名字,需要重新考虑换名字。
不好的例子:
doubletemp=Math.Sqrt(b*b-4*a*c);
好的例子:
doubledeterminant=Math.Sqrt(b*b-4*a*c);
(28)private/protected/internal/protectedinternal作用域内的实例化变量
开始小写,以后单词首字母大写。
使用前缀/后缀的场合,需要考虑变量名的易读性。
在用户定义的对象类型里,不要使用匈牙利标记法,使用Camel标记法。
其他的使用匈牙利标记法。
privateobjectobjCasing;
protectedobjectobjCasing;
internalPeoplepeopleCasing;//People是用户定义的对象
protectedinternalPeoplepeopleCasing;
(29)Public作用域内的实例化变量
开头字母大写,其后单词首字母大写。
尽量不要使用。
publicobjectPascalCasing;
(30)private/protected/internal/protectedinternal作用域内的公共变量
开始小写,其后单词首字母大写。
使用前缀/后缀的场合,需要考虑变量名的易读性。
在用户自定义的对象类型中,不要使用匈牙利标记法,应该使用Camel标记法。
其他的使用匈牙利标记法。
privatestaticobjectcamelCasing;
protectedstaticobjectcamelCasing;
internalstaticPeoplepeopleCasing;//People是用户定义的对象
protectedinternalstaticPeoplepeopleCasing;
(31)public作用域内的公共变量
开头字母大写,其后单词首字母大写。
尽量不要使用。
publicstaticobjectPascalCasing;
(32)局部(Local)变量
开始小写,其后单词首字母大写。
在用户自定义的对象类型中,不要使用匈牙利标记法,应该使用Camel标记法。
其他的使用匈牙利标记法。
objectobjCasing;
(33)大小写
命名时虽然区分大写字母和小写字母,但不能只是依靠这样来区别不同的名称。
4.GuideLine
(34)#Region/#EndRegion预处理指令
代码声明在#Region/#EndRegiondirective的领域里,其中包含关于该领域的说明。
例:
#Region"实例化变量"
privatestringname;
#EndRegion
#Region"Constructor"
publicMyClass(stringname)
{
this.name=name;
}
#EndRegion
(35)方法/属性的声明
在方法/属性的声明里,要明确地指定作用域。
(36)长行
一行的字符数最多是100位,如果超过100位就要进行分割。
分割的依据可以是:
(1)利用局部变量,
(2)在算术运算符/联结运算符处换行,(3)在逗号处换行(4)在优先级低的算符前换行。
例如:
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0)+Math.Pow(newRandom().NextDouble(),2.0));
'方針
(1)
doublexSquared=Math.Pow(newRandom().NextDouble(),2.0);
doubleySquared=Math.Pow(newRandom().NextDouble(),2.0);
doublelength=Math.Sqrt(xSquared+ySquared);
'方針
(2)
doublelength=Math.Sqrt(Math.Pow(newRandom().NextDouble(),2.0),
Math.Pow(newRandom().NextDouble(),2.0));
'方針(3)
LongMethodSignature(value[0],value[1],value[2],
value[3],value[4],value[5]);
'方針(4)
return(thisisobj)_
||(objisClass1_
andthis.Field==obj.Field);
(37)长行的类声明
类的声明较长的情况下在逗号,冒号处换行。
例:
如果是
publicclassLongNameClassImplemenation:
AbstractImplementation,IXmlSerializable,Icloneable
那么:
publicclassLongNameClassImplemenation:
AbstractImplementation,
IXmlSerializable,ICloneable
(38)长行的方法声明
方法的声明很长时在逗号处进行换行。
例:
publicvoidLongMethodSignature(inta,intb,intc
intd,inte,intf)
(39)抽象类和接口
尽量不使用抽象类(abstractClass)而是多使用接口(interface)。
abstractClass只有在既有已密封方法又有抽象方法的情况下使用。
理由:
接口(interface)允许多继承,而类(Class)只能是单继承。
如果只是继承了一个类,那么可惜不能再从其他类进行继承。
(40)公共变量
实例变量,尽量不用public修饰,而是设置合适的属性。
理由:
面向对象的标准。
类的内部状态是不能被随意访问的。
但是,如果全部满足下列条件,用public修饰实例变量,使之被直接访问也可以:
●如果那个实例变量与其他的实例变量是相互独立的,单独地改变它不会影响内部的整合性。
●一定书写get/set访问器
●依据将来传递时不被改变的原则进行接口变量的实装
即使不适合上述条件,但在非常关注效率的情况下,也可以没有这个限制。
(但是,请慎重对待)
(41)初始化
参照不要初始化为空值,而且不要进行两次初始化。
不好的例子:
publicclassPoorInitialization
{
privatestringname="initial_name";
publicPoorInitialization()
{
name="initial_name";
}
}
理由:
尽量减少与初始化有关的错误。
(42)避开static变量
尽量不用static变量(类变量)。
理由:
static变量,可以说是半全局变量。
这会导致代码的相互关系复杂化,会产生一定的副作用。
(43)private与protected
比起private,protected更常用。
理由:
定义为private的成员对于所在类以外的成员而言是不能访问的。
所以用户也就不能在子类中对它进行访问,作进一步的处理。
但是:
更喜欢使用private。
若用protected后,改变时会影响到整个类的继承关系。
(44)get/set访问器
不要胡乱地作成实例的属性(get/set访问器)并赋予public公共访问级别。
必要时,要做成某种属性/方法。
理由:
实例变量多是相互依存的,类的内部整合性不能破坏。
(45)变量隐藏
不要使用和基类的变量名相同的变量名。
理由:
这种情况一般会出现错误。
如果是有目的地使用可以这样。
(46)public方法
类的公共方法,以自动贩卖机的接口为例,进行易于理解,即使使用方法有误也不会破坏内部整合性的设计。
或者可能的情况下根据约定进行设计,用代码来表现类的不变条件,方法的执行前和执行后条件。
(47)状态取得和状态变更的分离
要设计的方法只能完成一项功能。
特别是不能在一个方法里面既进行状态变更又进行状态取得两种功能。
状态变更的方法的返回值为void.
因为:
1、1个方法完成一样功能简单易懂。
2、方便进行并行性的控制并易于确保程序不产生意外错误。
3、在子类的继承中,便于扩充。
(48)this中的return
尽管这是为用户使用的方便考虑,还是要尽量避免使用return返回this的方法。
理由:
A.Meth1().Meth2().Meth3()这样的连接,一般会产生同步上的问题。
(49)方法的多重定义
根据参数的类型尽可能的避免方法的重载(参数的个数可以不同),特别,在继承的复杂关系中。
例:
×:
overridevoidDraw(Rectanglerectangle)
overridevoidDraw(Pointpoint)
○:
voidDrawRectangle(Rectanglerectangle)
voidDrawPoint(Pointpoint)
(50)Equals()和GetHashCode()
如果撤销Object.Equals()方法,同时GetHashCode()方法也将被撤销。
反之亦然。
理由:
为了与哈希表(Hashtable)等相对应。
(51)Clone()
如果要使用Clone()方法,实例化ICloneable要明确写出来。
例:
usingSystem;
publicclassFoo:
ICloneable
{
publicobjectICloneable.Clone()
{
FoomyFoo=(Foo)this.Clone();
//...
}
}
理由:
简单的拷贝存在很多不好的情况。
(52)缺省的构造器
最好建立缺省的构造器(没有参数)。
理由:
在使用reflection时,可以利用Assembly.CreateInstance(TypeName)动态地生成对象。
(53)抽象类中的抽象方法
在abstract(抽象)类中,不写no-op方法,而是明确声明abstract方法。
对此设置为protected访问级别,为可能需要的实装做准备,这样可以在子类中实现方法功能。
理由:
因为.NET的IDE能查出没有实装的abstract方法,可以避免因为忘记实装而产生的错误。
(54)对象的同值比较
对象进行比较时使用Equals()方法,不能使用“=”。
特别是进行字符串的比较时,也不能使用“=”。
理由:
如果编程者想实现等值比较的话,那就应该使用Equals()。
并且,使用String进行比较时在OptionCompareText设定的是比较字符串不区分大小写。
原因:
在单元测试中,AssertEquals可以使用Equals(),可以简单地书写等值类。
(55)声明和初始化
局部变量,在声明时就进行初始化。
理由:
把有关变量的值假定为最小化。
不好的例子:
voidf(intstart)
{
inti,j;//没有赋予初始化值
//较多的代码
//...
i=start+1;
j=i+1;
//使用i,j
//...
}
好的例子:
voidf(intstart)
{
//较多的代码
//...
inti=start+1;
intj=i+1;
//使用i,j
//...
}
(56)局部变量不能重复利用
如果要重复使用局部变力,一定要重新进行声明并初始化。
理由:
把有关变量的值假定为最小化。
可以使编译程序达到最优化。
不好的例子:
voidf(intn,intdelta)
{
inti;//没有进行初始化
for(i=0;i { //使用i } for(i=0;i { if(...) { break; } } if(i! =n-1)//使用i进行循环的最后判断{ //... } i=n-delta*2;//再次使用 //... } 好的例子: 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;//利用其他的变量 //... } (57)大小比较运算符 最好使用“<”、”<=”,尽量不用”>“、”>=“ 理由: 统一大小方向,右侧的为大的方向,避免混乱。 (58)if/while条件中的"=" if,while的条件式中,不能使用“=“ 理由: 几乎所有这样的场合,都会出现错误。 (59)cast Cast形式转换时,尽量使用类型判断语句。 例(C为已知类,x是C的一个实例): Ccx=null; if(xisC) { cx=(C)x; } else { evasiveAction();//动作方法 } 理由: 这时,常常考虑的事情是“对象是不是类的实例呢? ”。 但是,cast不成功的场合是存在错误的。 如果能够判断出来的话,就没有这个限制了。 (60)异常类 异常类具有范围广大的特点,如果多用的话很容易造成程序流程难以阅读的问题。 使用异常类,相对于重新编写新的异常类来说,应尽可能利用.NET类库中已有的异常类 例如IOException,FileNotFoundException,ArgumentException等都是易使用的标准异常。 编写新的异常,也要研究这些现有的异常类的接口。 (61)改变方法的参数不好 原则上讲,方法中的参数是用来输入的,不能作为输出使用。 即在方法的内部改变参数的值是不提倡的。 不向输出参数代入新的对象。 不好的例子: voidMoveX(Pointp,intdx) { p.X=p.X+dx;//改变了参数(尽量避免) } 好的例子: voidMoveX(Pointp,intdx) { Pointp=NewPoint(p.X+dx,p.Y); //这个变量不会传到调用方
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- CodingStdCStreC 编程 规范 烟台 软件