C#编码规范.docx
《C#编码规范.docx》由会员分享,可在线阅读,更多相关《C#编码规范.docx(22页珍藏版)》请在冰豆网上搜索。
C#编码规范
第一章C#命名规范
1.1大小写约定
1.1.1标识符的大小写规则
Pascal大小写
将标识符的首字母和后面连接的每个单词的首字母都大写,例如:
BackColor
Camel大小写
标识符的首字母小写,而每个后面连接的单词的首字母都大写。
例如:
backColor
全部大写
仅对于由两个或者更少字母组成的标识符使用该约定。
例如:
System.IO,System.Web.UI等
表1-1不同类型的标识符的大小写规则
标识符
大小写方式
示例
类
Pascal
AppDomain
枚举类型
Pascal
ErrorLevel
枚举值
Pascal
FatalError
事件
Pascal
ValueChange
异常类
Pascal
WebException注意 总是以Exception后缀结尾。
只读的静态字段
Pascal
RedValue
接口
Pascal
IDisposable注意 总是以I前缀开始。
方法
Pascal
ToString
命名空间
Pascal
System.Drawing
参数
Camel
typeName
私有成员
Camel
userName
属性
Pascal
BackColor
受保护的实例字段
Camel
redValue属性优于使用受保护的实例字段。
公共实例字段
Pascal
RedValue属性优于使用公共实例字段。
1.1.2是否区分大小写
不要以为所有的编程语言都是区分大小写的,实际情况并非如此。
不应该仅仅通过大小写来区分名字。
如VB.NET在默认设置下是不区分大小写的。
基本的使用规则:
Ø不要使用要求区分大小写的名称
对于区分大小写和不区分大小写的语言,组件都必须完全可以使用。
不区分大小写的语言无法区分同一上下文中仅大小写不同的两个名称。
因此,在创建的组件或类中必须避免这种情况。
Ø不要创建仅是名称大小写有区别的两个命名空间
例如:
namespaceee.cummings;namespaceEe.Cummings;
Ø不要创建具有仅是大小写有区别的参数名称的函数
不正确的示例:
voidMyFunction(stringa,stringA)
Ø不要创建具有仅是大小写有区别的类型名称的命名空间
不正确的示例:
System.Windows.Forms.Pointp,System.Windows.Forms.POINTp
Ø不要创建具有仅是大小写有区别的属性名称的类型
不正确的示例:
intColor{get,set},intCOLOR{get,set}
Ø不要创建具有仅是大小写有区别的方法名称的类型
不正确的示例:
voidcalculate(),voidCalculate()
1.2通用命名约定
1.6.1单词的选择
Ø选择易阅读的名字
例如:
一个命名为HorizontalAlignment的属性就比AlignmentHorizontal更易于阅读。
Ø要更看重可读性,而不是更看重简短性
例如:
属性名CanScollHorizontally要胜过ScrollableX。
Ø不要使用下划线、连字符以及其他任何既非字母也非数字的字符
Ø不要使用匈牙利命名法
匈牙利命名法:
标识符的名字以一个或者多个小写字母开头作为前缀,前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。
例如:
m_lpszStr,表示指向一个以0字符结尾的字符串的长指针成员变量。
Ø避免使用与广泛使用的编程语言的关键字有冲突的标识符
1.6.2缩写
Ø不要将缩写或缩略形式用作标识符名称的组成部分
例如,使用GetWindow,而不要使用GetWin。
Ø不要使用计算机领域中未被普遍接受的缩写,使用众所周知的缩写
例如:
用UI作为UserInterface的缩写,用OLAP作为On-lineAnalyticalProcessing的缩写,HTML用来表示HypertextMarkupLanguage。
注:
关于一个给定的首字母缩写词是否众所周知,一个很好的衡量方法:
只要用搜索引擎在网上搜索该首字母缩写词,如果返回的前几个结果与期望相符,那么该首字母缩写词就有资格成为众所周知,否则的话,应该好好想想这个名字,不要直接把首字母缩写词拼写出来。
1.3为已有API的新版本命名
Ø要在创建已有API的新版本时使用与旧API相似的名字
例如:
//oldAPI
classAppDomain{
[Obsolete(“AppDomain.SetCachePathhasbeendeprecated.Please
useAppDomainSetUp.CachePathinstead.”)]
PublicvoidSetCachePath(stringpath){…}
}
//newAPI
classAppDomainSetUp{
publicstringCachePath{get{…};set{…};}
Ø要优先使用后缀而不是前缀来表示已有API的新版本
按字母的顺序显示标识符,因此旧API与新API在位置上会非常接近。
Ø要使用数字后缀来表示已有的API的新版本
例:
//oldAPI
[Obsolete(“Thistypeisobsolete.Pleaseusethenewversionofthesameclass,X509Certificate2.”]
publicclassX509Certificate{…}
//newAPI
publicclassX509Certificate2{…}
Ø考虑使用全新但有意义的表示符,而不是简单地给已有表示符添加后缀或前缀
Ø不要在标识符中使用”Ex”(或类似)后缀来区分相同API的不同版本
//oldAPI
[Obsolete(”Thistypeisobsolete….”)]
PublicclassCar{…}
//newAPI
publiccalssCarEx{…}//thewrongway
publicclassCarNew{…}//thewrongway
publicclassCar2{…}//therightway
publicclassAutomobile{..}//thierightway
Ø要在引入对64位整数(long)而非32位整数进行操作的新版API时使用”64”后缀
比如:
publicclassProcess{
//oldAPI
publicintPeakWorkingSet{get;}
publicintPagedMemorySize{get;}
//newAPI
publiclongPeakWorkingSet64{get;}
publiclongPagedMemorySize64{get;}
}
1.4名字空间的命名
Ø命名一般规则
.(|)[.][.]
例如:
Microsoft.VisualStudio
Microsoft.VisualStudio.Design
System.Runtime.Remoting
要用公司名称作为名字空间的前缀,避免与其它公司使用相同的名字;要用稳定的、与版本无关的产品名称作为名字空间第二层;使用Pascal大小写风格
Ø考虑在适当的时候,在名字空间中使用复数形式
例如:
System.Collections
Ø不要用相同的名字来命名名字空间与位于该名字中的类型
例如:
不要先将名字空间命名为Debug,然后又在该名字空间中提供一个名为Debug的类。
许多编译器要求用户在使用这样的类型时要加上完整的限定符。
Ø避免名字空间与类型名的冲突
Ø不要给位于同一应用程序模型的名字空间中的类型起相同的名字
例如:
不要给System.Web.UI.Adapter名字空间增加一个名字为Page的类型,因为System.Web.UI中已经包含了一个名为Page的类型。
Ø不要给类型起会与核心名字空间中的任何类型产生冲突的名字
例如:
绝对不要Stream来做类型名。
它会和System.IO.Stream产生冲突;同样的道理,不要给System.Diagnostics.Events名字空间添加一个名为EventLog的类型,因为System.Diagnostics名字空间已经包含了一个名为EventLog的类型。
1.5程序集和Dll的命名
Ø要为程序集合DLL选择提示性的名字
例如:
System.Data,这样容易就知道它的大致功能。
程序集合DLL的名字不一定要和命名空间相对应。
Ø按下面的模式给DLL命名
..dll
其中包含一个或多个以点号分隔的子句,例如:
Sungard.V8T.Controls.dll
1.6类、结构、接口的命名
1.6.1类的命名
Ø使用名词或名词短语命名类
Ø使用Pascal大小写
Ø少用缩写
Ø不要使用类型前缀
如在类名称上对类使用C前缀,例如,使用类名称FileStream,而不是CFileStream。
Ø不要使用下划线字符_
Ø可以以I开始的类名称的情况
有时候需要提供以字母I开始的类名称,虽然该类不是接口。
只要I是作为类名称组成部分的整个单词的第一个字母,这便是适当的。
例如,类名称IdentityStore就是适当的。
Ø有时使用复合单词命名派生的类,派生类名称的第二个部分应当是基类的名称
例如:
ApplicationException对于从名为Exception的类派生的类是适当的名称,原因是ApplicationException是一种Exception。
1.6.2接口的命名
Ø用名词或名词短语,或者描述行为的形容词命名接口
例如,接口名称IComponent使用描述性名词。
接口名称ICustomAttributeProvider使用名词短语。
名称IPersistable使用形容词。
Ø使用Pascal大小写
Ø少用缩写
Ø给接口名称加上字母I前缀,以指示该类型为接口
Ø在定义类/接口对时使用相似的名称
其中类是接口的标准实现,两个名称的区别应该只是接口名称上有字母I前缀。
Ø不要使用下划线字符_
1.6.3泛型类型参数的命名
泛型是.NET框架2.0以上版本的一个主要特性。
Ø要用描述性的名字来命名泛型类型参数,并加上T前缀
publicinterfaceISessionChannel{…}
publicdelegateTOutputConverter(TInputfrom);
Ø如果类型只有一个类型参数,考虑用T来命名参数类型
PublicintIComparer{…}
1.6.4常用类型的命名
如果要从.NET框架所包含的类型派生新类型,或者要实现.NET框架中的类型,那么请遵照表1-2的规范。
表1-2派生自或实现特定的核心类型的命名规则
基类
派生类型/实现类型的规范
System.Attribute
要给自定义的attribute类添加”Attribute”后缀
System.EventHandler
要给用于事件处理的委托添加”EventHandler”后缀
要给用户事件处理之外的那些委托添加”Callback”后缀
System.Delegate
不要给委托添加”Delegate”后缀
System.EventArgs
要添加”EventArgs”后缀
System.Enum
不要派生自该类,要用编成语言提供的关键字来代替。
例如在C#中,要用enum关键字
不要添加”Enum”或”Flag”后缀
System.Exception
要添加”Exception”后缀
System.Collections.IDictionary
System.Collocetion.Generic.
IDictionary
要添加”Dictionary”后缀。
System.Colections.IEnumerable
System.Colections.ICollection
System.Colections.IList
System.Colections.Generic
.IEnumerable
System.Colections.Generic.
ICollection
System.Colection.Generic.
IList
要添加”Collection”后缀
System.IO.Stream
要添加Stream后缀
System.Security.
CodeAccessPermisssion
System.Security.IPermission
要添加Permission后缀
1.6.5枚举的命名
Ø对于Enum类型和值名称使用Pascal大小写
Ø要用单数名词来命名枚举类型,除非它表示的是位域
publicenumConsoleColor{
Black,
Blue,
Cyan,
…
}
Ø要用复数名词来命名表示位域的枚举类型
[Flags]
publicenumConsoleModifiers{
Alt,
Control,
Shift
}
Ø不要给枚举添加前缀”Enum”
//Badnaming
publicenumColorEnum{
…
}
Ø不要给枚举名字添加”Flags”或”Flag”后缀
//Badnaming
publicenumColorFlags{
…
}
Ø不要给枚举类型值的名字添加前缀
如:
给ADO枚举添加”ad”前缀
publicenumImageMode{
ImageModeBitmap=0,
ImageModeIndexed=1,
ImageModeRgb=2
}
下面的命名会更好:
publicenumImageMode{
Bitmap=0,
Indexed=1,
ModeRgb=2
}
1.7类的成员的命名
1.7.1方法的命名
必须是动词或动词词组。
publicclassstring{
publicintCompareTo{…};
publicstring[]Split{…};
publicstringTrim();
}
1.7.2属性的命名
Ø要用名词、名词词组或形容来命名属性
publicclassstring{
publicintLength{get;}
}
Ø不要让属性名看起来与”Get”方法的名字相似
publicstringTextWriter{get{…}set{..}}
publicstringGetTextWriter{get{…}set{..}}//thebadway
Ø要用肯定性的短语来命名布尔属性
可以选择性给布尔属性添加”Is”、”Can”、”Has”等前缀,例:
CanRead要比Readable更容易理解,但Created却比IsCreated的可读性更好。
Ø考虑用属性的类型名来命名属性
publicenumColor{..}
publicclassControl{
publicColorColor{get{…}set{…}}
1.7.3事件的命名
Ø要用动词或动词短语来命名事件
如:
Clicked,Painting
Ø要用现在时和过去时来赋予事件名以之前和之后的概念
例如:
在窗口关闭前发生的Close事件应该命名为Closing,而在窗口关闭之后发生的应该命名为Closed。
Ø不要用”Before”或”After”前缀或后缀来区分前置和后置事件
Ø要在命名的事件处理函数时加上”EventHandler”后缀,参数用sender和e
例如:
publicdelegatevoidClickedEventHandler(objectsender,ClickedEventArgse);
Ø要在命名事件的参数时加上”EventArgs”后缀
例如:
publicclassClickedEventArgs:
EventArgs{
intx;
inty;
publicClickedEventArgs(intx,inty){
this.x=x;
this.y=y;
}
publicintX{get{returnx;}}
publicintY{get{returny;}}
}
1.7.4字段的命名
Ø使用Pascal大小写风格
Ø要用名词或名词短语
Ø不要给字段添加前缀
例如:
不要用”g_”或”s_”来区分静态和非静态字段。
1.8参数的命名
Ø使用Camel大小写风格
publicclassString{
publicboolContains(stringvalue);
publicstringRemove(intstartIndex,intcount);
}
Ø要使用具有描述性的参数名
Ø根据参数的意思而不是参数的类型来命名参数
1.9资源的命名
Ø要在命名资源关键字(resourcekey)时使用Pascal大小写风格
Ø要使用标识符的名字具有描述性而不是使名字变短
Ø不要使用CLR语言特有的关键字
Ø要用点号来给标识符清楚地划分层次
例如:
设计菜单系统的资源
Menus.FileMenu.Close.Text
Menus.FileMenu.Close.Color
Menus.FileMenu.SaveAs.Text
1.10控件的命名约定
控件包括.NET提供的控件、自定义控件、第三方控件。
使用的控件数量在不断的增长,
不再采用控件缩写的命名规则,原因是新增一个控件类型就要给它约定一个简写,简写很容易产生冲突、简写多了也很难记忆,因此采用如下命名规则:
控件的名称:
[业务含义][控件类型名称]
例如:
用户名输入框UserNameTextBox,用户类型选择下拉框UserTypeDropDownList
第二章C#编程风格约定
2.1通用风格约定
2.1.1花括号的使用
花括号内只有一条语句,避免省略花括号,即使编程语言允许这样做
例如:
if(someExpression)
DoSomething();
2.2.1空格的使用
Ø不要在成员的名字和左圆括号之间加空格
正确:
Foo()
错误:
Foo()
Ø不要在左方括号之后或右方括号间加空格
正确:
x=dataArray[index]
错误:
x=dataArray[index]
Ø不要在控制流语句之前加空格
正确:
while(x==y)
错误:
while(x==y)
Ø避免在二元操作之前后之后加空格
最好如此:
if(x==y){…}
可以接受:
if(x==y){…}
2.3.1缩进的使用
Ø要使用4个连续的空格符来进行缩进,不要用制表符(tab)来进行缩进
Ø要对代码块中的内容进行缩进
if(someExpression){
DoSomething();
}
Ø要对case代码块中的内容进行缩进
Switch(someExpression){
Case0:
DoSomething();
Break;
..
}
2.2注释
Ø不要用注释来描述一些对任何人都显而易见的事
Ø避免使用块注释语法(/*…*/),即使注释会有多行,也最好是使用单行注释语法(//…)
Ø不要把注释放在行尾
//Avoid
PublicclassArrayList{
Privateintcount;//-1indicatesuninitializearray
}
2.3文件的组织
Ø不要在一个源文件中包含一个以上的公用类型
一个文件中有多个内部类型是允许的
Ø要使用相同的名字来命名源文件及其包含的公用类型
例如:
String类应该在String.cs文件中,而List类则应该在List.cs文件中
Ø要用相同的层次结构来组织文件目录和名字空间
应该把System.Collection.Generic.List的源文件放在System\Collections\Generic
Ø考虑根据下面给出的顺序和组别来对成员进行分组
所有字段;所有的构造函数;公有属性及受保护的属性;方法;事件;所有显示实现的接口成员;内部成员;私有成员;所有嵌套类型
Ø要把不能公开访问的成员和显示实现的接口成员分别放在自己的#region中
#regioninternalmembers
…
#endregion
#regionprivatememebers
…
#endregion
Ø要考虑在每个组别内根据字母顺序来组织成员
Ø考虑根据由简单到复杂的顺序来组织重载成员
Ø要把using指令放在名字空间的声明之外
UsingSytem;
NamespaceSystem.Collections{
…
}
第三章异常处理规范
3.1抛出异常
Ø要通过抛出异常的方式来报告操作失败
如果成员无法成功地完成它应该完成的任务,那么应该认为这就是操作失败并抛出异常。
Ø考虑通过调用System.Enviroment.FailFast(.NetFramewok2.0新特性)来终止进程
如果代码遇到了严重的问题,已经无法继续安全地执行,可以通过这种方式终止进程。
例如:
栈被严重破坏,在这种情况下,操作系统无法将异常往栈的上层继续传递,应用程序的不变性(即继续传递异常)无法得到满足,因此只能终止。
Ø不要让公有成员根据某个选项来决定是否抛出异常
//baddesign
publicTypeGetType(stringname,boolthrowOnError)
Ø不要把异常用作公有成员的返回值或输出参数
//baddesign
publicExceptionDoSomething(){…}
Ø考虑使用辅助方法来创建异常
从不同的地方抛出同一个异常是很常见的,为了