C# 应遵循的编码规范.docx
- 文档编号:12245226
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:21
- 大小:26.49KB
C# 应遵循的编码规范.docx
《C# 应遵循的编码规范.docx》由会员分享,可在线阅读,更多相关《C# 应遵循的编码规范.docx(21页珍藏版)》请在冰豆网上搜索。
C#应遵循的编码规范
C#编码规范
深圳伟图科技有限公司
2011年10月
(试行)
目录
1.简介1
2.适用范围1
3.代码组织与风格1
3.1缩进1
3.2空行1
3.3函数长度1
3.4花括号(“{”,“}”)1
5.注释2
5.1.注释的基本约定2
5.2.注释类型2
5.2.1.块注释2
5.2.2.行注释2
5.2.3.尾随注释2
5.3.注释哪些部分2
5.4.程序修改注释3
5.5程序区块注释3
6.命名4
6.1.命名的基本约定4
6.2.各种标识符类型的命名约定5
6.2.1.程序集命名5
6.2.2.命名空间命名5
6.2.3.类和接口命名5
6.2.4.方法命名5
6.2.5.变量命名6
7.声明6
8.表达式和语句6
9.类型设计规范6
9.1.类型和命名空间6
9.2.类型和接口的选择7
9.3.静态类设计7
9.4.枚举设计7
10.成员设计规范8
10.1.成员设计的一般规范8
10.2.方法的重载规范;8
10.3.属性和方法的选择9
10.4.属性的设计规范:
10
10.5.构造函数的设计规范10
10.6.字段设计规范10
10.7.参数的设计规范11
10.7.1.参数设计中枚举和布尔参数的选择规范11
11.扩展性设计规范11
12.异常处理规范12
12.1.异常类型选择规范12
12.2.异常处理规范12
12.3.标准异常类的使用:
12
12.3.1.Exception与SystemException12
12.3.2.InvalidOperationException12
12.3.3.ArgumentException,ArgumentNullException,ArgumentOutOfRangeException13
12.3.4.NullRefernceException,IndexOutOfRangeException,AccessViolationException13
12.3.5.StackOverflowException:
13
12.3.6.OutOfMemoryException:
13
12.4.自定义异常类型设计规则:
13
12.5.异常与性能13
13.其他规定13
14.参考文档14
1.简介
本规范为伟图公司开发人员编写高效可靠的C#代码的标准、约定和指南。
它以安全可靠的软件工程原则为基础,使代码易于理解、维护和增强,提高生产效率。
同时,将带来更大的一致性,使软件开发团队的效率明显提高。
2.适用范围
本规范适用于公司所有的C#源代码,为详细设计,代码编写和代码审核提供参考和依据。
3.代码组织与风格
3.1缩进
•要使一个代码块内的代码都统一缩进一个长度(4个字符)。
在VS2010可由IDE自动完成(”设置文档格式”快捷键)。
3.2空行
•适当的增加空行,来增加代码的可读性。
•在类,接口之间要有两行空行:
•在方法之间要有一行空行:
3.3函数长度
•每个函数有效代码(不包括注释和空行)长度不得超过50行。
3.4花括号(“{”,“}”)
•开括号“{”要放在块的所有者的下一行,单起一行;
•闭括号“}”要单独放在代码块的最后一行,单起一行。
5.注释
5.1.注释的基本约定
注释应该增加代码的清晰度;
保持注释的简洁,不是任何代码都需要注释的,过多的注释反而会影响代码的可读性。
注释不要包括其他的特殊字符。
先写注释,后写代码,注释和代码一起完成.
如果语句块(比如循环和条件分枝的代码块)代码太长,嵌套太多,则在其结束“}”要加上注释,标志对应的开始语句。
如果分支条件逻辑比较复杂,也要加上注释。
在VS环境中通过配置工程编译时输出XML文档文件可以检查注释的完整情况,如果注释不完整会报告编译警告;
5.2.注释类型
5.2.1.块注释
•主要用来描述文件,类,方法,算法等,放在所描述对象的前边。
•对类和接口的注释用IDE编辑器输入“///”自动生成的格式,另外再附加自定义的标签如下:
///
•方法只用自动格式即可
5.2.2.行注释
主要用在方法内部,对代码,变量,流程等进行说明。
整个注释占据一行。
5.2.3.尾随注释
•与行注释功能相似,放在代码的同行,但是要与代码之间有足够的空间,便于分清。
例:
intm=4;//注释
•如果一个程序块内有多个尾随注释,每个注释的缩进要保持一致。
5.3.注释哪些部分
项目
注释哪些部分
参数
参数用来做什么
任何约束或前提条件
字段/属性
字段描述
类
类的目的
已知的问题
类的开发/维护历史
接口
目的
它应如何被使用以及如何不被使用
局部变量
用处/目的
成员函数注释
成员函数做什么以及它为什么做这个
哪些参数必须传递给一个成员函数
成员函数返回什么
已知的问题
任何由某个成员函数抛出的异常
成员函数是如何改变对象的
包含任何修改代码的历史
如何在适当情况下调用成员函数的例子适用的前提条件和后置条件
成员函数内部注释
控制结构
代码做了些什么以及为什么这样做
主要局部变量
难或复杂的代码
处理顺序
5.4.程序修改注释
•新增代码行的前后要有注释行说明,对具体格式不作要求,但必须包含作者,新增时间,新增目的。
在新增代码的最后必须加上结束标志;
•删除代码行的前后要用注释行说明,删除代码用注释原有代码的方法。
注释方法和内容同新增;删除的代码行建议用#regionXXX#endregion代码段折叠,保持代码文件干净整洁
•修改代码行建议以删除代码行后再新增代码行的方式进行(针对别人的代码进行修改时,必须标明,对于自己的代码进行修改时,酌情进行)。
注释方法和内容同新增;
5.5程序区块注释
•C#提供了region注释,可用于代码的任意区块的注释并且可以收缩隐藏,提高程序的可读性,但是不要在一个单一的命名空间、类、接口、函数再添加region注释,因为VS已经能够提供相应的注释和收缩功能。
6.命名
6.1.命名的基本约定
•要使用可以准确说明变量/字段/类的完整的英文描述符,如firstName。
对一些作用显而易见的变量可以采用简单的命名,如在循环里的递增(减)变量就可以被命名为”i”。
•要尽量采用项目所涉及领域的术语。
•要采用大小写混合,提高名字的可读性。
为区分一个标识符中的多个单词,把标识符中的每个单词的首字母大写。
不采用下划线作分隔字符的写法。
有两种适合的书写方法,适应于不同类型的标识符:
PasalCasing:
标识符的第一个单词的字母大写;
camelCasing:
标识符的第一个单词的字母小写。
下表描述了不同类型标识符的大小写规则:
标识符
大小写
示例
命名空间
Pascal
namespaceCom.Techstar.ProductionCenter
类型
Pascal
publicclassDevsList
接口
Pascal
publicinterfaceITableModel
方法
Pascal
publicvoidUpdateData()
属性
Pascal
PublicintLineLength{…}
事件
Pascal
publiceventEventHandlerChanged;
私有字段
Camel
privatestringfieldName;
非私有字段
Pascal
publicstringFieldName;
枚举值
Pascal
FileMode{Append}
参数
Camel
publicvoidUpdateData(stringfieldName)
局部变量
Camel
stringfieldName;
•避免使用缩写,如果一定要使用,就谨慎使用。
同时,应该保留一个标准缩写的列表,并且在使用时保持一致。
•对常见缩略词,两个字母的缩写要采用统一大小写的方式
(示例:
ioStream,getIOStream);
多字母缩写采用首字母大写,其他字母小写的方式
(示例:
getHtmlTag);
•避免使用长名字(最好不超过15个字母)。
•避免使用相似或者仅在大小写上有区别的名字。
6.2.各种标识符类型的命名约定
6.2.1.程序集命名
•公司域名(Wayto)+项目名称+模块名称(可选),例如:
深圳地铁三维程序集:
Wayto.SzMetro3D;
深圳地铁三维业务逻辑程序集:
Wayto.SzMetro3D.Business;
6.2.2.命名空间命名
•采用和程序集命名相同的方式:
公司域名(Wayto)+项目名称+模块名称。
另外,一般情况下建议命名空间和目录结构相同。
例如:
中心系统:
Wayto.ProductionCenter;
中心系统下的用户控件:
Wayto.ProductionCenter.UserControl;
中心系统业务逻辑:
Wayto.ProductionCenter.Business;
中心系统数据访问:
Wayto.ProductionCenter.Data;
6.2.3.类和接口命名
•类的名字要用名词;
•避免使用单词的缩写,除非它的缩写已经广为人知,如HTTP。
•接口的名字要以字母I开头。
保证对接口的标准实现名字只相差一个“I”前缀,
例如对IComponent的标准实现为Component;
•泛型类型参数的命名:
命名要为T或者以T开头的描述性名字,例如:
publicclassList
publicclassMyClass
•对同一项目的不同命名空间中的类,命名避免重复。
避免引用时的冲突和混淆;
6.2.4.方法命名
•第一个单词一般是动词
•如果方法返回一个成员变量的值,方法名一般为Get+成员变量名;如若返回的值是bool变量,一般以Is作为前缀。
另外,如果必要,考虑用属性来替代方法,具体建议见10.1.2节;
•如果方法修改一个成员变量的值,方法名一般为:
Set+成员变量名。
同上,考虑用属性来替代方法;
6.2.5.变量命名
•按照使用范围来分,我们代码中的变量的基本上有以下几种类型,类的公有变量;类的私有变量(受保护同公有);方法的参数变量;方法内部使用的局部变量。
这些变量的命名规则基本相同,见标识符大小写对照表。
区别如下:
•不要用_或&作为第一个字母;
•尽量要使用短而且具有意义的单词;
•单字符的变量名一般只用于生命期非常短暂的变量。
i,j,k,m,n一般用于integer;c,d,e一般用于characters;s用于string
•如果变量是集合,则变量名要用复数,例如List
7.声明
•每行要只有一个声明,如果是声明i,j,k之类的简单变量可以放在一行;
•除了for循环外,声明要放在块的最开始部分。
for循环中的变量声明可以放在for语句中。
如:
for(inti=0;I<10;i++)。
•避免块内部的变量与它外部的变量名相同。
8.表达式和语句
•每行只有一条语句。
9.类型设计规范
•要确保每个类型由一组定义明确,相互关联的成员组成,而不仅仅是一些无关功能的随机集合;
9.1.类型和命名空间
•要用命名空间把类型组织成相关域的层次结构。
例如:
界面层:
Wayto.ProductionCenter;
业务逻辑层:
Wayto.ProductionCenter.Business;
数据访问层:
Wayto.ProductionCenter.Data;
•避免过深的命名空间;
•避免太多的命名空间;
9.2.类型和接口的选择
•要优先采用类而不是接口。
接口的缺点在于语义变化时改变困难。
注意接口并不是协定,把协定和实现分开并非一定用接口实现,用基类和抽象类同样可以表达;
•建议使用抽象类而不是接口来解除协定与实现间的偶合;
•要定义接口,来实现类似多重继承的效果;
精心定义接口的标志是一个接口只做一件事情。
关键是接口的协定需要保持不变,如果一个接口包含太多功能,那么这个胖接口产生变化的机会就会大得多。
9.3.静态类设计
静态类是一个只包含静态成员的类,它提供了一种纯面向对象设计和简单性之间的一个权衡,广泛用来提供类似于全局变量或一些通用功能。
•要少用静态类。
静态类应该仅用作辅助类;
•避免把静态类当作杂物箱。
每个静态类都应该有其明确目的;
•不要在静态类中声明或覆盖实例成员;
9.4.枚举设计
•要用枚举来加强那些表示值的集合的参数,属性以及返回值的类型性;
•要优先使用枚举而不是静态常量。
例如:
//不好的写法
publicstaticclassColor
{
publicstaticintRed=0;
publicstaticintGreen=1;
publicstaticintBlue=2;
}
//好的写法
publicenumColor
{
Red,
Green,
Blue
}
•不要把枚举用于开放的场合,例如操作系统的版本,朋友的名字等;
•枚举中不要提供为了今后使用而保留的枚举值;
10.成员设计规范
方法,属性,事件,构造函数以及字段等统称为成员。
10.1.成员设计的一般规范
10.2.方法的重载规范;
•避免在重载中随意的给参数命名。
如果两个重载中的某个参数表示相同的输入,那么该参数的名字应该相同。
例如:
publicclassString
{
//好的写法
publicintIndexOf(stringvalue){...}
publicintIndexOf(stringvalue,intstartIndex){...}
//不好的写法
publicintIndexOf(stringvalue){...}
publicintIndexOf(stringstr,intstartIndex){...}
}
•避免重载成员的参数顺序不一致。
在所有的重载中,同名参数应该出现在相同的位置。
例如:
publicclassEventLog
{
publicEventLog();
publicEventLog(stringlogName);
publicEventLog(stringlogName,stringmachineName);
publicEventLog(stringlogName,stringmachineName,stringsource);
}
•较短的重载应该仅仅调用较长的来实现。
另外,重载如果需要扩展性,把最长重载做成虚函数。
例如:
publicclassString
{
publicintIndexOf(strings)
{
//调用
returnIndexOf(s,0);
}
publicintIndexOf(strings,intstartIndex)
{
//调用
returnIndexOf(s,startIndex,s.Length);
}
publicvirtualintIndexOf(strings,intstartIndex,intCount)
{
//实际的代码
}
}
•要允许可选参选为null。
这样做是为了避免调用者调用之前需要检查参数是否null。
例如:
//允许为null时的调用
DrawGeometry(brush,pen,geometry);
//不允许为null时的调用
if(geometry==null)DrawGeometry(brush,pen);
elseDrawGeometry(brush,pen,geometry);
10.3.属性和方法的选择
•基本原则是方法表示操作,属性表示数据。
如果其他各方面都一样,优先使用属性而不是方法。
•要使用属性,如果该成员表示类型的逻辑attribue
•如果属性的值存储在内存中,而提供属性的目的仅仅是为了访问该值,要使用属性而不要使用方法
•如果该操作每次返回的结果不同,那么要使用方法。
例如来自于.netframework的例子:
Guid.NewGuid();
DateTime.Now;
•如果该操作比访问字段慢一个或多个数量级,要使用方法。
•如果该操作有严重的副作用,要使用方法。
10.4.属性的设计规范:
•如果不应该让调用方法改变属性值,要创建只读属性;
•不要提供只写属性;
•要为所有的属性提供合理的默认值,这样可以确保默认值不会导致漏洞或效率低的代码;
•要允许用户以任何顺序来设置属性的值;
•避免在属性的获取方法抛出异常。
•属性的获取方法应该是个简单的操作,不应该有任何的条件。
如果一个获取方法会抛出异常,它该设计为方法。
10.5.构造函数的设计规范
•建议提供简单的构造函数,最好是默认构造函数。
简单的构造函数增强易用性;
•考虑扩展性,如果构造函数设计的不自然,建议用静态的工厂方法来替代构造函数;
•要把构造函数的参数用作设置主要属性的便捷方法。
如果构造函数参数仅用来设置属性,应和属性名称相同。
仅有大小写的区别;
•要在构造函数中做最少的工作。
任何其他处理应该推迟到需要的时候;
•要在类中显式地声明公用的默认构造函数,如果这样的构造函数是必须的。
如果没有显式默认构造函数,添加有参构造函数时往往会破坏已有使用默认构造函数的代码;
•避免在对象的构造函数内部调用虚成员。
这样在扩展设计的时候会导致难以理解的现象;
10.6.字段设计规范
•要只用常量字段来表示永远不会改变的量。
否则会导致兼容性问题。
下面是正确的例子:
publicstructInt32
{
publicconstintMaxValue=0x7fffffff;
publicconstintMinValue=unchecked((int)0x80000000);
}
•要用公有的静态只读字段来定义预定义的对象实例。
例如:
publicstructColor
{
publicstaticreadonlyColorRed=newColor(0x0000FF);
}
10.7.参数的设计规范
•要用类结构层次中最接近基类类型来作为参数的类型,同时要保证该类型能够提供成员所需的功能。
例如:
•要设计一个集合遍历的方法,那么参数应该是IEnbumerable为参数,而不应该是IList,这样方法具有更强的适应性。
10.7.1.参数设计中枚举和布尔参数的选择规范
•要用枚举。
在代码阅读,书写中,枚举都比布尔的可读性好很多。
例如:
//使用布尔型,阅读的时候不会轻易了解参数的含义
FileStreamf=File.Open(“1.txt”,true,false);
//使用枚举型
FileStreamf=File.Open(“1.txt”,CasingOptions.CaseSenstive,FileMode.Open);
•不要使用布尔参数,除非百分之百肯定绝对不需要两个以上的值。
即使此时,采用枚举往往也可以提供更好的可读性,如上例。
•考虑在构造函数中,对确实只有两种状态值的参数以及用来初始化布尔属性的参数使用布尔类型;
11.扩展性设计规范
•如果没有恰当理由,不要把类密封起来。
这些理由包括:
A)类为静态类;
B)类的受保护成员保存了高度机密信息;
C)类继承了许多虚成员,逐个密封的代价太高,不如密封整个类;
D)不要在密封类中声明保护成员或虚成员,因为无法覆盖其实现;
•建议用保护成员用于高级定制。
它提供了扩展性,同时也避免了公用接口过于复杂;
•不要使用虚成员,除非有合适的理由;
•建议只有在绝对必须的时候才用虚成员提供扩展性,并使用TemplateMethod模式;
•要优先使用受保护的虚成员,而不是公有虚成员。
公有成员通用调用受保护的虚成员的方式来提供扩展性;
12.异常处理规范
•异常的思想是只对错误采用异常处理:
逻辑和编程错误,设置错误,被破坏的数据,资源耗尽,等等。
通常的法则是系统在正常状态下以及无重载和硬件失效状态下,不应产生任何异常。
异常处理时可以采用适当的日志机制来报告异常,包括异常发生的时刻;
•一般情况下不要使用异常实现来控制程序流程结构;
•使用异常而不要用错误代码来报告错误;
•要通过抛出异常的方式来报告操作失败。
如果成员无法成功地完成它应该做的任务,那么应该抛出异常;
12.1.异常类型选择规范
•优先考虑使用System命名空间中已有的异常,而不是自己创建新的异常类型;
•要使用最合理,最具针对性的异常。
例如,对参数为空,应抛出System.ArgutmentNullException,而不是System.ArgutmentException
12.2.异常处理规范
´不是百分之百确定的情况,不要吞掉异常;
•建议捕获特定类型的异常,如果理解该异常在具体环境当中产生的原因;
•不要捕获不应该捕获的异常,通常应该允许异常沿着调用栈传递;
•进行清理工作时要用try-finally,避免使用try-catch;
•要在捕获并重新抛出异常时使用空的throw语句,这是保持调用栈的最好方法
12.3.标准异常类的使用:
12.3.1.Exception与SystemException
•不要抛出这两种类型的异常;
•避免捕获这两种异常,除非是在顶层的异常处理器中;
12.3.2.InvalidOperationException
•对象处于不正确状态时抛出;
12.3.3.ArgumentException,ArgumentNullException,ArgumentOutOfRangeException
•如果传入的是无效参数,要抛出参数异常,尽可能使用位于继承层次末尾的类型;
•要在抛出异常时设置ParaName属性;
12.3.4.NullRefernceException,IndexOutOfRangeException,AccessViolationException
•不要显示抛出或捕获;
12.3.5.StackOverflowException:
•不要显示抛出或捕获;
12.3.6.OutOfMemoryException:
•不要显示抛出或捕获;
12.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 应遵循的编码规范 遵循 编码 规范