C#编码规范.docx
- 文档编号:9364442
- 上传时间:2023-05-18
- 格式:DOCX
- 页数:24
- 大小:28.35KB
C#编码规范.docx
《C#编码规范.docx》由会员分享,可在线阅读,更多相关《C#编码规范.docx(24页珍藏版)》请在冰点文库上搜索。
C#编码规范
C#编码标准(试行)
本文档约定C#编码基本标准,未尽之处可以参加《.Net设计规范(.Net约定、惯用法与模式)》一书。
《.Net设计规范(.Net约定、惯用法与模式)》中存在与本标准约定不一致的地方,实践中须以本文档为准。
本文档作为试行标准,后期将会根据需要进一步进行修改完善。
1命名约定和风格
1.1类型名、方法名和常量沿用Pascal命名规范
publicclassSomeClass
{
constintDefaultSize=100;
publicSomeMethod()
{
}
}
1.2局部变量和方法参数使用camel命名规范
intnumber;
voidMyMethod(intsomeNumber)
{
}
1.3接口名加前缀I:
interfaceIMyInterface
{
}
1.4私有成员变量前加前缀m_。
1.5自定义属性类加后缀Attribute。
1.6自定义异常类加后缀Exception。
1.7方法命名可为具有描述意义的动词或者动词短语,一般使用“动词+对象”,如ShowDialog()。
1.8类型、常量、变量命名可为具有描述意义的名词或者名词短语。
1.9有返回值的方法名中需要描述此返回值,如GetObjectState()。
1.10使用描述性变量名:
A.避免使用单个字母作为变量名,如i或t,用index或temp来代替。
B.避免对公共成员或受保护成员使用匈牙利标记法。
C.避免使用缩写,如把number写成num。
1.11始终使用C#中的预定义类型,不要使用System命名空间中的别名,如:
使用object,不要使用Object;
使用string,不要使用String;
使用int,不要使用Int32。
1.12对于泛型,用该类型的首字符代替,当处理.Net的Type类型时才使用Type作后缀:
正确的做法:
publicclassLinkedList
{
}
避免的做法:
publicclassLinkedList
{
}
1.13使用有意义的命名空间名称(如产品名称或公司名称),限定一律使用“公司名称+产品名称+组建名称”,如SunwinRIVSCSLogin。
1.14避免使用完全限定类型名,用using语句代替。
1.15避免在命名空间里面使用using语句。
1.16把所有的framework命名空间放在一起,把自定义和第三方命名空间放在下面:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingMyCompany;
usingmyControls;
1.17采用委托推断,不要显示实例化委托:
delegatevoidSomeDelegate();
publicvoidSomeMethod()
{
}
SomeDelegatesomeDelegate=SomeMethod;
1.18严格保持缩进,不要使用Tab或不标准的缩进,如一个空格,建议使用四个空格(开发工具默认缩进作为标准)。
1.19注释缩进要和其注释的代码保持在同一列。
1.20单行代码的注释直接放在被注释代码行之后的同行,并且使用4个空格隔开。
1.21整块代码的注释需要放在被注释代码块之前的上行。
1.22所有的注释都要通过拼写校验。
1.23所有的成员变量都必须在顶部声明,用一行把它们和属性、方法等隔开:
publicclassMyClass
{
intm_Number;
stringm_Name;
publicvoidSomeMethod1()
{
}
publicvoidSomeMethod1()
{
}
}
1.24合理使用空行:
A.在每个类、接口声明之后、每个函数定义结束之后都要加上空行。
B.在一个函数体或者代码块内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
1.25定义局部变量时,尽量使它靠近第一次使用的地方。
1.26文件名需要能够反映它所包含的类。
1.27当使用局部类型和指定局部文件时,用局部逻辑角色为它们命名,如:
在MyClass.cs文件中
publicpartialclassMyClass
{
}
在MyClass.Designer.cs文件中
publicpartialclassMyClass
{
}
1.28用左大括号({)时换一行,用右大括号(})时换一行。
1.29对于匿名方法,模拟常规方法的编码格式,与匿名委托声明对起(这和使用大括号必修换行是一致的)
delegatevoidSomeDelegate(stringsomeString);
正确的做法:
publicvoidInvokeMethod()
{
SomeDelegatesomeDelegate=delegate(stringname)
{
MessageBox.Show(name);
}
SomeDelegate("Juval");
}
避免的做法:
publicvoidInvokeMethod()
{
SomeDelegatesomeDelegate=delegate(stringname){MessageBox.Show(name);}
SomeDelegate("Juval");
}
1.30无参数的匿名方法要使用空括号,只有当该匿名方法能使用在任意委托上时才可省略空括号:
delegatevoidSomeDelegate();
正确的做法:
publicvoidInvokeMethod()
{
SomeDelegatesomeDelegate=delegate()
{
MessageBox.Show(name);
}
SomeDelegate("Juval");
}
避免的做法:
publicvoidInvokeMethod()
{
SomeDelegatesomeDelegate=delegate
{
MessageBox.Show(name);
}
SomeDelegate("Juval");
}
1.31二元运算和三元运算中,操作数和操作符之间使用一个空格隔开;一元运算中,操作数和操作符之间无需使用空格隔开。
1.32函数声明、定义和调用涉及多个参数之时,首参数和末参数与括号之间不用使用空格隔开,参数之间使用一个空格隔开,空格位于逗号之后。
1.33if、for、while、switch等可由开发环境自动生成控制结构或者语句,一律保留生成之时的默认风格。
2编码实践
2.1版本和版权声明
版权和版本声明位于文件开头,主要内容和版式如下:
/*
*Copyright(c)2011
*深圳市赛为智能股份有限公司(研发中心)
*Allrightsreserved.
*
*文件名称:
filename.cs
*文件标识:
GUID
*摘要:
简要描述本文件的内容
*
*当前版本:
1.1
*作者:
输入作者(或修改者)名字
*完成日期:
2011年2月24日
*
*取代版本:
1.0
*原作者:
输入原作者(或修改者)名字
*完成日期:
2011年2月14日
*/
2.2避免将多个类文件放到同一个文件中。
2.3一个文件定义的类型应属于同一命名空间,避免在同一个文件中定义多个命名空间的类型。
2.4一个文件的代码最好避免超过500行(机器产生的代码除外)。
2.5方法最好避免超过25行。
2.6方法避免超过5个参数,使用结构体传递多个产生。
2.7每行不要超过80个字符。
2.8不要手动编辑任何机器代码。
A.如果要更改机器代码,则更改其格式和风格以符合本代码标准。
B.尽可能采用局部类,以分离出需要维护的部分。
2.9避免对显而易见的内容作注释,代码应该是自解释的,有可读性强的变量和方法组成的好的代码应该不需要注释。
2.10仅对操作假设、算法思路等写文档。
2.11避免方法级别的文档。
A.对API文档采用大量的外部文档。
B.方法注释仅作为对其他开发人员的提示。
2.12除了“0”和“1”,不要用数值硬编码,声明一个常量代替。
2.13仅对本来就是常来的值使用const修饰符,例如一周的天数。
2.14避免对只读的常量使用const,在此情况下使用readonly修饰符:
publicclassMyClass
{
publicconstintDaysInWeek=7;
publicreadonlyintNumber;
publicMyClass(intsomeValue)
{
Number=someValue;
}
}
2.15对任何假设都要采用断言,平均每五行就有一行是断言:
usingSystem.Diagnostics;
objectGetObject()
{
}
objectsomeObject=GetObject();
Debug.Assert(someObject!
=null);
2.16每行代码都应该以白盒测试的方式运行过一遍。
2.17仅捕获需要显示处理的异常。
2.18在抛出异常的catch语句中,总是抛出最初异常(或由最初异常构建的另一个异常)以保持最初错误的堆栈位置。
try
{
}
catch(Exceptionexception)
{
MessageBox.Show(exception.Message);
throw;
}
2.19避免将错误代码作为方法的返回值。
2.20避免定义自定义的异常类。
2.21定义自定义异常时:
A.从Exception类中派生出自定义异常类。
B.提供自定义序列化。
2.22避免在一个程序集中有多个Main()方法。
2.23仅对需要的类型标记为public,其他标记为internal。
2.24避免友元程序集,它们增加了程序集之间的耦合。
2.25避免代码依赖于从一个特定的位置运行程序集。
2.26最小化应用程序的程序集代码(即EXE客户端程序集),用类库来包含业务逻辑。
2.27避免对枚举提供明确的值。
正确的做法:
publicenumColor
{
Red,Green,Blue
}
避免的做法:
publicenumColor
{
Red=1,Green=2,Blue=3
}
2.28避免对枚举指定类型。
避免的做法:
publicenumColor:
long
{
Red,Green,Blue
}
2.29if语句始终使用{},即使该if语句只包含一个语句。
2.30避免使用三重?
:
条件运算符。
2.31避免在布尔条件语句中调用函数,将函数返回值指定到一个局部变量,然后检查该变量:
boolIsEveryThingOK()
{
}
避免的做法:
if(IsEveryThingOK())
{
}
正确的做法:
boolok=IsEveryThingOK();
if(ok)
{
}
2.32总是使用从0开始的数组。
2.33总是使用一个for循环显示地初始化一个引用类型的数组。
publicclassMyClass
{
}
constintArraySize=100;
MyClass[]array=newMyClass[ArraySize];
for(intindex=0;index { array[index]=newMyClass[]; } 2.34不提供public或protected成员变量,而是使用属性。 2.35避免使用new继承修饰符,而是使用override。 2.36对非密封类总是将public或protected方法标记为virtual。 2.37除非涉及到互操作,永远不要使用unsafe代码。 2.38避免显示类型转换,使用as操作符防御性地进行转换类型。 Dogdog=newGermanShepherd(); GermanShepherdshepherd=dogasGermanShepherd; if(shepherd! =null) { } 2.39调用委托前始终检查委托是否为空。 2.40不要提供public的事件成员变量,而是使用事件访问器。 2.41避免定义事件处理代理,而是使用GenericEventHandler。 2.42避免显示地触发事件,使用EventHelper防御性的分布事件。 2.43总是使用接口。 2.44类和接口中方法和属性的个数的比例最少必须保持在2: 1。 2.45避免接口中只含一个成员。 2.46争取接口中含有三到五个成员。 2.47每个接口中不要超过二十个成员,实际应用中不超过十二个成员。 2.48避免把事件作为接口的成员。 2.49当使用抽象类的同时,提供一个接口。 2.50在类层次关系上暴露接口。 2.51优先使用显示接口实现。 2.52不要假定一种类型能支持某个接口,防御性地为接口查询是否支持该接口。 SomeTypeobj1; IMyInterfaceobj2; obj2=obj1asIMyInterface; if(obj2==null) { obj2.Method(); } else { } 2.53永远不要硬编码将呈现给用户的字符串,而是使用资源。 2.54永远不要硬编码布署时可能修改的字符串,例如连接字符串。 2.55用String.Empty代替""。 避免的做法: stringname=""; 正确的做法: stringname=String.Empty; 2.56构建一个长字符串时,使用StringBuilder,不要使用string。 2.57不要为结构体提供方法。 A.参数化的构造函数是鼓励使用的。 B.可以重载算符。 2.58当提供静态成员变量时,总是提供一个静态的构造函数。 2.59只要可以用前期绑定,就不要用后期绑定。 2.60对应用程序进行日志和跟踪。 2.61除非在switch语句中跳转,否则永远不要使用goto语句。 2.62switch语句中总是使用带断言的defaultcase。 intnumber=SomeMethod(); switch(number) { case1: Trace.WriteLine("Case1: "); break; case2: Trace.WriteLine("Case2: "); break; default: Debug.Assert(false); break; } 2.63除非在一个构造函数中调用另外一个构造函数,否则不要使用this引用。 publicclassMyClass { publicMyClass(stringmessage) { } publicMyClass(): this("Hello") { } } 2.64除非和子类成员名发生了同名冲突或在调用基类构造函数时,否则不要使用base访问基类的成员。 publicclassDog { publicDoy(stringname) { } virtualpublicvoidBark(inthowLong) { } } publicclassGermanShepherd: Dog { publicGermanShepherd(stringname): base(name) { } publicoverridevoidBark(inthowLong) { base.Bark(howLong); } } 2.65不要使用GC.AddMemoryPressure()。 2.66不要依赖HandleCollector。 2.67以正确的方式实现Dispose()和Finalize()方法。 2.68总是在默认情况下以unchecked模式运行代码(为了提高性能),当进行容易上限溢位或下限溢位的操作时,要在checked模式下运行: intCalcPower(intnumber,intpower) { intresult=1; for(intcount=1;count<=power;count++) { checked { result*=number; } } returnresult; } 2.69避免方法调用的显示排除(#if-#endif),用条件方法代替。 publicclassMyClass { [Conditional("MySpecialCondition")] publicvoidMyMethod() { } } 2.70不要在使用泛型的代码中对System.Object进行类型转化,使用约束或as运算符。 classSomeClass { } 避免的做法: classMyClass { voidSomeMethod(Tt) { objecttemp=t; SomeClassobj=(SomeClass)temp; } } 正确的做法: classMyClass SomeClass { voidSomeMethod(Tt) { SomeClassobj=t; } } 2.71不要在泛型接口中定义约束条件,接口级别的约束常常可以用强类型代替。 publicclassCustomer { } 避免的做法: publicinterfaceIList Customer { } 正确的做法: publicinterfaceICustomerList: IList { } 2.72不要在接口中定义与方法相关的约束。 2.73如果一个类或方法提供泛型和非泛型实现,推荐使用泛型实现。 2.74在实现从等价的非泛型接口衍生出来的泛型接口时(例如IEnumerable classMyCollection IEnumerable { IEnumerable { } IEnumeratorIEnumerable.GetEnumerator() { IEnumerable returnenumerable.GetEnumerator(); } } 3项目设置和项目结构 3.1总是以四级警告建立项目。 3.2在发布版中将警告当中错误,推荐在调试版中将警告当中错误。 3.3避免不要抑制特定的编译警告。 3.4总是在应用程序的配置文件中显示地说明支持的运行时版本。 3.5避免显示地自定义版本重定向和绑定到CLR程序集。 3.6避免显示预处理定义(#define),使用项目设置定义条件编译常量。 3.7不要在AssemblyInfo.cs中放任何逻辑。 3.8除了在AssemblyInfo.cs以外,不要在任何文件中放程序集属性。 3.9在AssemblyInfo.cs中提供所有字段的值,例如公司名称、描述、版权说明等。 3.10所有程序集引用应该使用相对路径。 3.11禁止在程序集间进行循环引用。 3.12避免多模块的程序集。 3.13避免使用Exception窗口篡改异常处理。 3.14尽量对同一逻辑应用程序中(通常是一个解决方案)的所有程序集和客户端使用统一的版本号,应该使用技术手段自动化实现。 3.15配置文件命名为App.config,并将其包括在项目中。 3.16修改默认项目结构以适应项目标准布局,并使所有项目文件夹和文件使用统一的结构。 3.17发布版中应该包含调试符号。 3.18对程序集进行签名,包括客户端应用程序。 3.19使用密码保护的键值。 4与Framework相关的指南 4.1多线程操作 4.1.1使用同步域,避免手工同步,手工控制经常导致死锁和竞争条件。 4.1.2不要向同步域外调用。 4.1.3使用回调方法管理异步调用完成,不要为调用完成而等待、问询或阻塞。 4.1.4始终为现场命名。 4.1.5不要对一个线程调用Suspend()或Resum()。 4.1.6除了以下情况,不要调用Thread.Sleep(): A.对于强制上下文切换,Thread.Sleep(0)是可接受的优化技术。 B.在测试和模拟代码中,Thread.Sleep()是可接受的。 4.1.7不要调用Thread.SpinWait()。 4.1.8不要调用Thread.Abort()来终止线程,使用一个同步对象来通知线程结束。 4.1.9避免显示设置现场优先级来控制执行,可以基于任务的语义来设置线程优先级。 4.1.10不要读取ThreadState的属性值,使用Thread.IsAlive()确定线程是否终止或是仍然有效。 4.1.11不要为关闭程序而将线程类型设置为后台线程,使用一个监视器或其他监视实体来确定关闭线程。 4.1.12除非能保证线程关联性,否则不要使用线程本地存储。 4.1.13不要调用Thread.MemoryBarrier()。 4.1.14在调用Thread.Join()之前,一定要检查是否是在加入自己的线程。 4.1.15使用lock()语句,而不要显示的Monitor操作。 4.1.16始终将lock()语句包含在其保护的对象内。 4.1.17可以使用同步方法代替lock()语句。 4.1.18避免片段死锁。 4.1.19避免使用监视器来等待或激活对象,使用手工方法或自动复位事件代替。 4.1.20不要使用volatile变量,使用锁定对象或自动的方法,以保证访问是其确定性和线程安全的,不要使用Thread.VolatileRead()、Thread.VolatileWrite(),或volatile修饰符。 4.1.21避免增加线程池中的线程最大值。 4.1.22不要堆砌lock()语句,堆砌lock()语句并不能提供原子锁定,使用WaitHandle.WaitAll()代替。 4.2序列化 4.2.1推荐使用二进制格式器。 4.2.2将序列化事件处理方法标记为priva
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 编码 规范