C 代码规范.docx
- 文档编号:13526515
- 上传时间:2023-06-15
- 格式:DOCX
- 页数:16
- 大小:22.52KB
C 代码规范.docx
《C 代码规范.docx》由会员分享,可在线阅读,更多相关《C 代码规范.docx(16页珍藏版)》请在冰点文库上搜索。
C代码规范
C#代码规范
1、前言
本文档定义了一些通用的代码规范和准则,一般情况下本文档适用于项目组所有项目,特殊情况下,如果客户有自己的代码规范,以客户的代码优先。
2、大小写约定
2.1、大小写样式,本文中将出现两种大小写样式,这里先分别定义:
Pascal大小写
将标识符的首字母和后面连接的每个单词的首字母都大写。
可以对三字符或更多字符的标识符使用Pascal大小写。
例如:
BackColor
Camel大小写
标识符的首字母小写,而每个后面连接的单词的首字母都大写。
例如:
backColor
匈牙利命名法
基本原则是:
变量名=属性+类型+对象描述。
例如:
lblName
2.2、标识符大小写规则
2.2.1、下表中列出常见的代码元素的样式规范和示例
标识符
规则
示例
类
Pascal
AppDomain
枚举类型
Pascal
ErrorLevel
枚举值
Pascal
Warning
事件
Pascal
ValueChanging,ValueChanged
异常类
Pascal
WebException
只读的静态字段
Pascal
CurrentUser
接口
Pascal
IDisposable
方法
Pascal
ToString
命名空间
Pascal
System.Data
参数
Camel
typeName
属性
Pascal
Name
常量
全大写
MAXLENGTH,LENGTH_MAX
Web或Win控件
匈牙利
txtName
2.2.2、除了遵循以上大小写约定外还需注意以下约定(除常量为特例):
✓如果标识符由多个单词组成,请不要在各单词之间使用分隔符,如下划线(“_”)或连字符(“-”)等。
而应使用大小写来指示每个单词的开头。
✓所有公共的成员如:
方法、属性,都应使用Pascal大小写样式
2.3、首缩写词的大小写规则
2.3.1、首字母缩写词
首字母缩写词是由术语或短语中各单词的首字母构成的单词。
例如,HTML是HypertextMarkupLanguage的首字母缩写。
为了方便编码规范的实施,本文规定受字母缩写词必须至少为两个单词,正好为两个单词的首字母缩写词称其为“短型首字母缩写词”,两个单词以上的称其为“长型首字母缩写词”
2.3.2、单缩写词
单缩写词是一个单词的缩写。
例如,ID是identifier的缩写。
注意:
可在标识符中使用的两个缩写词是ID和OK。
在采用Pascal大小写格式的标识符中,这两个缩写词的大小写形式应分别为Id和Ok。
如果在采用大小写混合格式的标识符中将这两个缩写词用作首个单词,则它们的大小写形式应分别为id和ok。
2.3.3、首字母缩写词有以下大小写规则:
短型首字母缩写词在Pascal大小写样式中,两个字母都应大写。
在Camel大小写样式中,如果是首个单词,两个字母都应小写。
例如:
✓名为DBRate的属性是一个采用Pascal大小写格式的标识符,它使用短型首字母缩写词(DB)作为首个单词。
✓名为ioChannel的参数是一个采用大小写混合格式的标识符,它使用短型首字母缩写词(IO)作为首个单词。
长型首字母缩写词,在任何大小写样式中都视为一个单词。
例如:
✓名为XmlWriter的类是一个采用Pascal大小写格式的标识符,它使用长型首字母缩写词作为首个单词。
✓名为htmlReader的参数是一个采用大小写混合格式的标识符,它使用长型首字母缩写词作为首个单词。
2.3.4、复合词的大小写规则:
所有复合词在任何大小写样式中都视为一个完整单词。
例如,hashtable是一个紧凑格式的复合词,应将其视为一个单词并相应地确定大小写。
如果采用Pascal大小写格式,则该复合词为Hashtable;如果采用大小写混合格式,则该复合词为hashtable。
若要确定某个单词是否是紧凑格式的复合词,请查阅最新的词典。
2.3.5、区分大小写
大小写准则只是为了使标识符更易于阅读和辨认。
不能将大小写规则用作避免库元素之间的命名冲突的手段。
3、通用命名约定
3.1、通用命名约定讨论的是如何为库元素选择最适当的名称。
这些准则适用于所有标识符。
后面各节讨论特定元素(如命名空间或属性)的命名。
3.2、名称的选择与命名原则
3.2.1、请选择易读的标识符名称
例如,英文属性名称HorizontalAlignment比AlignmentHorizontal更具可读性。
3.2.2、可读性比简洁性更重要
例如,属性名称CanScrollHorizontally比ScrollableX(指X轴,但意义不明确)更好。
3.2.3、不要使用下划线、连字符或任何其他非字母数字字符
3.2.4、不要使用匈牙利表示法
匈牙利表示法是在标识符中使用一个前缀对参数的某些元数据进行编码,如标识符的数据类型。
3.2.5、避免使用与常用编程语言的关键字冲突的标识符
虽然符合CLS的语言必须提供将关键字用作普通字的方法,最佳做法不要求强制开发人员了解如何实现。
对于大多数编程语言,语言参考文档都会提供语言所使用的关键字列表。
3.3、缩写和首字母缩写单词
尽量避免使用缩写或首字母缩写词。
这类名称的可读性较差。
同样,要确定某个首字母缩写词是否已受到广泛认可也是很困难的。
不要将缩写或缩略形式用作标识符名称的组成部分。
例如,使用OnButtonClick而不要使用OnBtnClick。
除非必要,不要使用任何未被广泛接受的首字母缩写词。
3.4、程序集和DLL的名称
所有程序集名称都必须和项目的命名空间相对应。
3.5、命名空间的名称
3.5.1、所有命名空间都需以公司名或产品名为根命名空间。
为命名空间选择的名称应指示命名空间中的类型所提供的功能。
例如,命名空间包含的类型允许开发人员使用套接字通过网络进行通信。
3.5.2、命名空间名称的一般格式如下:
(<公司>|<产品>|<技术>)[.<性质>][.<子命名空间>]
例如,ClearCost.Repository.Interface。
3.5.3、命名空间和其中的类型不要使用相同的名称。
例如,不要在将“Debug”用作命名空间名称的同时,又在该命名空间中提供一个名为“Debug”的类。
3.5.4、命名空间一般准则
不要引入宽泛的类型名称,如Element、Node、Log和Message。
在通常情况下,这样极可能导致类型名称冲突。
应对宽泛的类型名称进行限定(例如FormElement、XmlNodeEventLog、SoapMessage)。
3.5.5、应用程序命名空间准则
不要在单个应用程序模型内为命名空间中的多个类型指定相同的名称。
例如,如果要编写Windows窗体应用程序开发人员要使用的特殊控件库,则不应引入名为Checkbox的类型,因为该应用程序模型已存在同名类型。
3.5.6、核心命名空间准则
不要指定会与核心命名空间中的任何类型发生冲突的类型名称。
例如,不要使用Directory作为类型名称,因为这会与Directory类型冲突。
3.5.7、技术命名空间准则
不要分配会与单个技术命名空间内的其他类型发生冲突的类型名称。
不要引入会导致技术命名空间的类型与应用程序模型命名空间中的类型发生冲突的类型名称(除非该技术不用于该应用程序模型)。
3.6、接口、类和结构的名称
通常,类型名称应该是名词短语,其中名词是由类型表示的实体。
例如,Button、Stack和File都具有名称,用于标识由类型表示的实体。
从开发人员的角度选择标识实体的名称;名称应反映使用场合。
下面的准则适用于如何选择类型名称:
✓按照Pascal大小写格式,使用名词或名词短语(或偶尔使用形容词短语)为类、接口和值类型命名。
✓不要为类名加前缀(如字母C)。
接口不适用此规则,它应以字母I开头。
✓考虑在派生类的末尾使用基类名称。
例如,从Stream继承的Framework类型以Stream结尾,从Exception继承的类型以Exception结尾。
✓为接口名称加上字母I前缀,以指示该类型为接口。
✓在定义类/接口对(其中类是接口的标准实现)时,一定要确保类和接口的名称除接口名称以字母I为前缀外,二者应完全相同。
例如,Framework提供IAsyncResult接口和AsyncResult类。
✓用描述性名称为泛型类型参数命名,除非单个字母的名称已完全可以自我说明而无需描述性名称。
✓对具有一个单字母类型参数的类型,考虑将字母T用作这些类型的类型参数名称。
✓将字母T作为描述性类型参数名称的前缀。
✓考虑在参数名称中指示置于类型参数上的约束。
例如,约束于ISession的参数可称为TSession。
3.7、常见类型的名称
下面的准则提供的命名约定有助于开发人员了解某些类的使用场合:
✓向自定义属性类添加Attribute后缀。
✓ObsoleteAttribute和AttributeUsageAttribute是符合此准则的类型名称。
✓向在事件中使用的类型(如C#事件的返回类型)的名称添加EventHandler后缀。
✓AssemblyLoadEventHandler是符合此准则的委托名称。
✓向不是事件处理程序的委托的名称添加Callback后缀。
事件处理程序一般以EventHandler结尾
✓不要向委托添加Delegate后缀。
✓向扩展System.EventArgs的类添加EventArgs后缀。
✓不要从System.Enum类派生;使用当前所用语言支持的关键字。
例如,在C#中应使用enum关键字。
✓向从System.Exception继承的类型添加Exception后缀。
✓向实现IDictionary或IDictionary
注意,是特定类型的集合,但此准则的优先级高于以下更为一般的集合准则。
✓向实现IEnumerable、ICollection、IList、IEnumerable
✓向从继承的类型或实现的类型添加Permission后缀。
注意:
以上准则中提及的从某个其他类型继承的类型,指的是所有的继承者,而不只是直接继承的类型。
例如,“向从Exception继承的类型添加Exception后缀”这一准则意味着在继承层次结构中具有Exception的任何类型都应该使用以Exception结尾的名称。
每条这样的准则还用来保留指定的后缀;除非类型满足该准则表述的条件,否则不应使用该后缀。
例如,如果类型不是从Exception直接或间接继承的,则类型名称不能以Exception结尾。
3.8、枚举的名称
不要在枚举值名称中使用前缀。
例如,不要对ADO枚举使用ad之类的前缀,也不要对多格式文本枚举使用rtf之类的前缀,依此类推。
这还意味着不应在枚举值名称中包含枚举类型名称。
下面的代码示例演示了不正确的枚举值命名。
正确
错误
publicenumTeams
{
Alpha,
Beta,
Delta
}
publicenumTeams
{
TeamsAlpha,
TeamsBeta,
TeamsDelta
}
不要将Enum用作枚举类型的后缀。
不要在标志枚举的名称中添加Flags作为后缀(位域枚举可例外)。
对枚举使用单数名称,除非枚举值是位域。
对使用位域值的枚举(也称为标志枚举)使用复数名称。
3.9、类型成员的名称
类型包含以下几种成员:
方法、属性、字段、事件
3.9.1、方法的名称
使用动词或动词短语作为方法的名称。
通常,方法对数据进行操作,因此,使用动词描述方法的操作可使开发人员更易于了解方法所执行的操作。
定义由方法执行的操作时,应从开发人员的角度仔细选择明确的名称。
不要选择描述方法如何执行其操作的动词,也就是说,不要使用实现细节作为方法名称。
3.9.2、属性的名称
使用名词、名词短语或形容词作为属性的名称。
名词短语或形容词适合于属性,因为属性保存数据。
不要使用与Get方法同名的属性。
例如,不要将一个属性命名为EmployeeRecord,又将一个方法命名为GetEmployeeRecord。
开发人员会不知道使用哪个成员来完成其编程任务。
使用肯定性短语作为布尔值属性的名称(如使用CanSeek而不使用CantSeek)。
可以为布尔值属性添加前缀(如Is、Can或Has),但要注意使用得当。
考虑为属性提供与其类型相同的名称。
如果某个属性已强类型化为某个枚举,则该属性可与该枚举同名。
例如,如果有一个名为CacheLevel的枚举,则返回其中一个枚举值的属性也可以命名为CacheLevel。
3.9.3、事件的名称
使用动词或动词短语作为事件的名称。
在为事件命名时,使用现在时或过去时表示时间上的前后概念。
例如,在窗口关闭之前引发的关闭事件可命名为“Closing”,在窗口关闭之后引发的关闭事件可命名为“Closed”。
不要使用“Before”或“After”作为前缀或后缀来指示之前和之后发生的事件。
使用后缀EventHandler命名事件处理程序(用作事件类型的委托)。
在事件处理程序签名中使用命名为“sender”和“e”的两个参数。
sender参数的类型应为Object,e参数应是EventArgs的实例或继承自EventArgs的实例。
使用EventArgs后缀命名事件参数类。
3.9.4、字段的名称
字段的命名准则适用于静态公共字段和静态受保护字段。
不要定义公共实例字段。
在字段名称中使用Pascal大小写格式。
使用名词或名词短语作为字段的名称。
3.10、参数名称
选择适当的参数名称可极大改善库的可用性。
适当的参数名称应指示该参数会影响的数据或功能。
对参数名称使用Camel大小写。
使用描述性参数名称。
在大多数情况下,参数名称及其类型应足以确定参数的用法。
考虑使用反映参数含义的名称而不是反映参数类型的名称。
在开发人员工具和文档中,参数的类型通常都是可见的。
3.11、资源的名称
本主题中准则适用于可本地化的资源,如错误信息和菜单文本。
在资源键中使用Pascal大小写格式。
提供描述性标识符,而不要提供短标识符。
尽量保持标识符的简洁性,但不要牺牲可读性。
使用点分隔符(“.”)以清晰的层次结构表示标识符。
例如,和等名称符合此准则。
对异常消息资源使用下面的命名约定。
资源标识符应由异常类型名称加上异常的短标识符构成,二者之间以点分隔。
例如,ArgumentException.BadEnumValue符合此准则。
4、代码规范
4.1、目录结构
每个命名空间原则都有单独的文件目录,每个类存储于一个单独的文件中
4.2、换行
当一个表达式过长时,可以按照以下原则进行换行
✓在逗号后换行
✓在操作符后换行
✓尽量保持运算模块的完整性
✓新行应该和上一行在起始处对齐
Exampleofbreakingupmethodcalls:
longMethodCall(expr1,expr2,
expr3,expr4,expr5);
Examplesofbreakinganarithmeticexpression:
Prefer:
Bad:
var=a*b/(c-g+f)+var=a*b/(c-g+
4*z;f)+4*z;
4.3、缩进
应该总是使用TAB进行代码缩进,而不是使用空格
4.4、空行
合理使用空行可以增加代码的可读性,使代码逻辑紧疏有序。
4.4.1、在下列情况下,应该使两个空行对代码进行分隔。
但就尽量保持每个类一个文件的原则避免。
✓类与接口的定义之间
✓类与类的定义之间
✓类与枚举的定义之间
4.4.2、以下情况,应该使用一个空行对代码进行分隔
✓两个方法之间
✓两个属性之间
✓方法与属性之间
✓方法内的局部变量定义与逻辑语句之间
✓方法内的明显的逻辑块之间
✓备注与其他语句之间(非被备注的语句)
✓Return语句与其它语句之间
Perfer:
Bad:
Publicinttest()Publicinttest()
{{
intindex=0;intindex=0;
doSomething;doSomething;
returnindex;
returnindex;}
}
4.5、代码格式化
4.5.1、Using语句应该在类的顶端,并进行排序。
(System置顶)
4.5.2、对类内代码进行分组,推荐顺序如下:
✓成员变量
✓构造函数
✓公共属性
✓公共方法
4.5.3、对代码进行分组时,同时遵循访问符和可见性原则
✓Public
✓Protected
✓Internal
✓Private
4.5.4、对某一接口的实现,使用region进行隔离
4.5.5、如果类或方法有多个Attribute时,每个单独占用一行。
Prefer:
bad:
[Attribute1][Attribute1,Attribute2]
[Attribute2]PublicClassMyClass
PublicClassMyClass
{{
}}
4.6、注释
4.6.1、使用//或///进行注释,禁止在正式代码中使用/*……*/注释。
4.6.2、除了文件头部,禁止使用类似以下的‘花式注释’
//********************
//Commentblock
//********************
4.6.3、不要用注释去解释显而易见的逻辑,好的代码应该是自注释的。
4.6.4、如果有必要,可以对复杂逻辑进行描述性注释
4.6.5、推荐文件头部注释格式
//Copyright(C)Accegile
//FileName:
CodeStandSample.cs
//Filedescription:
//
//Createidentifier:
klu2007-02-06
//
//Modificationidentifier:
klu2007-02-07
//Modificationdescription:
//
//Modificationidentifier:
//Modificationdescription:
5、语言使用最佳实践
5.1、基本原则
✓显式的定义所有成员的访问符。
Prefer:
Bad:
publicvoidWriteEvent(stringmessage);voidWriteEvent(stringmessage);
✓根据代码版本手动增加程序集的版本号,而不总是1.0。
(AssemblyVersionAttributeinassemblyinfo)
✓如果有必要使用unsafe代码,尽量把它们写到一个单独的程序集里
5.2、变量和类型
✓在定义变量时,最好立即进行初始化。
比如:
inti=0;strings=string.Empty;
✓使用简单的值类型,而不是其对应的类或结构。
比如使用int而不是Int32.
✓只对简单类型定义常量,对于复杂类型,应定义只读或静态只读变量,在构造时进行初始化。
✓尽量使用泛型以避免装箱和拆箱操作
✓除非明确知道子类型,应尽量避免直接类型转换,应该使用as,并进行null检查。
Example:
objectdataObject=LoadData();
Datasetds=dataObjectasDataset;
If(ds!
=null)
{}
✓在字符串前边使用@符号,而不是对字符串进行逐个转义
✓对大量的字符串连接使用string.Format或StringBuilder.
✓尽量避免在未知长度的循环中使用字符串连接,代以StringBuilder.
✓不要对字符串使用=和string.Empty或””进行比较,应使用string.IsNullOrEmpty.
✓尽量避免字符串的隐式转换,应使用Compare方法。
尤其是在循环中,可能引发较大的性能损失。
Example
PerferBad
If(String.Compare(order.Name,name,true))If(()==name)
✓避免用表达式去重复计算一个bool值
PerferBad
If(isValid)If(isValid==true)
6、异常处理
✓只在你需要处理异常的地方去catch它,而不是随意的catch和重新抛出
✓不要使用try-catch去进行代码流控制,而是用验证去避免造成异常
PerferBad
If(conn.State==ConnectionState.Open)try{
{Conn.Close();
Conn.Close();}
}catch{}
✓允许异常冒泡,而不是重新抛出异常。
除非你想要代之以一个自定义异常,此时应以原异常做为它的InnerException.
PerferBad
catch(Exceptionex)catch(Exceptionex)
{{
Log(ex)Log(ex);
throw;throwex;
}}
catch(Exceptionex)catch(Exceptionex)
{{
Log(ex)Log(ex);
thrownewCustomException(“msg”,ex);thrownewCustomException(“msg”);
}}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 代码规范 代码 规范