C#命名规范.docx
《C#命名规范.docx》由会员分享,可在线阅读,更多相关《C#命名规范.docx(26页珍藏版)》请在冰豆网上搜索。
C#命名规范
C#书写规范
一、命名
对于理解应用程序的逻辑流,命名方案是最有影响力的一种帮助。
名称应该说明“什么”而不是“如何”。
通过避免使用公开基础实现(它们会发生改变)的名称,可以保留简化复杂性的抽象层。
例如,可以使用GetNextStudent(),而不是GetNextArrayElement()。
命名原则是:
选择正确名称时的困难可能表明需要进一步分析或定义项的目的。
使名称足够长以便有一定的意义,并且足够短以避免冗长。
唯一名称在编程上仅用于将各项区分开。
表现力强的名称是为了帮助人们阅读;因此,提供人们可以理解的名称是有意义的。
不过,请确保选择的名称符合适用语言的规则和标准。
以下几点是推荐的命名方法。
1、方法、属性、变量规范
·避免容易被主观解释的难懂的名称,如方面名AnalyzeThis(),或者属性名xxK8。
这样的名称会导致多义性。
·在面向对象的语言中,在类属性的名称中包含类名是多余的,如Book.BookTitle。
而是应该使用Book.Title。
·使用动词-名词的方法来命名对给定对象执行特定操作的例程,如CalculateInvoiceTotal()。
·在允许函数重载的语言中,所有重载都应该执行相似的函数。
·只要合适,在变量名的末尾或开头加计算限定符(Avg、Sum、Min、Max、Index)。
·在变量名中使用互补对,如min/max、begin/end和open/close。
·鉴于大多数名称都是通过连接若干单词构造的,请使用大小写混合的格式以简化它们的阅读。
另外,为了帮助区分变量和例程,请对例程名称使用Pascal大小写处理(CalculateInvoiceTotal),其中每个单词的第一个字母都是大写的。
对于变量名,请使用camel大小写处理(documentFormatType),其中除了第一个单词外每个单词的第一个字母都是大写的。
·布尔变量名应该包含Is,这意味着Yes/No或True/False值,如fileIsFound。
·在命名状态变量时,避免使用诸如Flag的术语。
状态变量不同于布尔变量的地方是它可以具有两个以上的可能值。
不是使用documentFlag,而是使用更具描述性的名称,如documentFormatType。
(此项只供参考)
·即使对于可能仅出现在几个代码行中的生存期很短的变量,仍然使用有意义的名称。
仅对于短循环索引使用单字母变量名,如i或j。
·可能的情况下,尽量不要使用原义数字或原义字符串,如Fori=1To7。
而是使用命名常数,如Fori=1ToNUM_DAYS_IN_WEEK以便于维护和理解。
二、代码书写规范
格式化使代码的逻辑结构很明显。
花时间确保源代码以一致的逻辑方式进行格式化,这对于您和你的开发小组,以及以后维护源代码的其他开发人员都有很大的帮助。
以下几点是推荐的格式化方法。
·建立标准的缩进大小(如四个空格),并一致地使用此标准。
用规定的缩进对齐代码节。
·在发布源代码的硬拷贝版本时使用特定的字体以及字号(新宋体、小五号)。
·在括号对对齐的位置垂直对齐左括号和右括号,如:
for(i=0;i<100;i++)
{
;
}
也可以使用倾斜样式,即左括号出现在行尾,右括号出现在行首,如:
for(i=0;i<100;i++){
;
}
无论选择哪种样式,请在整个源代码中使用那个样式。
·沿逻辑结构行缩进代码。
没有缩进,代码将变得难以理解,如:
if(expression)
{
//
//此处填写你的代码块;
//
}
if(expression)
{
//
//此处填写你的代码块;
//
}
else
{
//
//此处填写你的代码块;
//
}
缩进代码会产生出更容易阅读的代码,如:
if(expression)
{
if(expression)
{
//
//此处填写你的代码块;
//
}
else
{
//
//此处填写你的代码块;
//
}
}
·为注释和代码建立最大的行长度,以避免不得不滚动源代码编辑器,并且可以提供整齐的硬拷贝表示形式。
·在大多数运算符之前和之后使用空格,这样做时不会改变代码的意图。
但是,C++中使用的指针表示法是一个例外。
·使用空白为源代码提供结构线索。
这样做会创建代码“段”,有助于读者理解软件的逻辑分段。
·当一行内容太长而必须换行时,在后面换行代码中要使用缩进格式,如下:
stringinserString="InsertIntoTableName(username,password,email,sex,address)"
+"Values('Soholife','chenyp','soholife@','male','深圳福田')";
·只要合适,每一行上放置的语句避免超过一条。
例外是C、C++、C#或JScript中的循环,如for(i=0;i<100;i++)。
·编写HTML时,建立标准的标记和属性格式,如所有标记都大写或所有属性都小写。
另一种方法是,坚持XHTML规范以确保所有HTML文档都有效。
尽管在创建Web页时需折中考虑文件大小,但应使用带引号的属性值和结束标记以方便维护。
·编写SQL语句时,对于关键字使用全部大写,对于数据库元素(如表、列和视图)使用大小写混合。
·在物理文件之间在逻辑上划分源代码。
·将每个主要的SQL子句放在不同的行上,这样更容易阅读和编辑语句,例如:
SELECTFirstName,LastName
FROMCustomers
WHEREState='WA'
·将大的复杂代码段分为较小的、易于理解的模块。
三、注释
软件文档以两种形式存在:
外部的和内部的。
外部文档(如规范、帮助文件和设计文档)在源代码的外部维护。
内部文档由开发人员在开发时在源代码中编写的注释组成。
不考虑外部文档的可用性,由于硬拷贝文档可能会放错地方,源代码清单应该能够独立存在。
外部文档应该由规范、设计文档、更改请求、错误历史记录和使用的编码标准组成。
内部软件文档的一个难题是确保注释的维护与更新与源代码同时进行。
尽管正确注释源代码在运行时没有任何用途,但这对于必须维护特别复杂或麻烦的软件片段的开发人员来说却是无价的。
以下几点是推荐的注释方法:
·如果用C#进行开发,请使用XML文档格式,如下面方法的注释:
///
///得到某人的年龄
///
///用户名
///用户年龄
publicintGetUserAge(stringuserName)
{
//
//此处写你的程序代码
//
}
·修改代码时,总是使代码周围的注释保持最新。
·在每个例程的开始,提供标准的注释样本以指示例程的用途、假设和限制很有帮助。
注释样本应该是解释它为什么存在和可以做什么的简短介绍。
·避免在代码行的末尾添加注释;行尾注释使代码更难阅读。
不过在批注变量声明时,行尾注释是合适的;在这种情况下,将所有行尾注释在公共制表位处对齐。
·避免杂乱的注释,如一整行星号。
而是应该使用空白将注释同代码分开。
·避免在块注释的周围加上印刷框。
这样看起来可能很漂亮,但是难于维护。
·在部署之前,移除所有临时或无关的注释,以避免在日后的维护工作中产生混乱。
·如果需要用注释来解释复杂的代码节,请检查此代码以确定是否应该重写它。
尽一切可能不注释难以理解的代码,而应该重写它。
尽管一般不应该为了使代码更简单以便于人们使用而牺牲性能,但必须保持性能和可维护性之间的平衡。
·在编写注释时使用完整的句子。
注释应该阐明代码,而不应该增加多义性。
·在编写代码时就注释,因为以后很可能没有时间这样做。
另外,如果有机会复查已编写的代码,在今天看来很明显的东西六周以后或许就不明显了。
·避免多余的或不适当的注释,如幽默的不主要的备注。
·使用注释来解释代码的意图。
它们不应作为代码的联机翻译。
·注释代码中不十分明显的任何内容。
·为了防止问题反复出现,对错误修复和解决方法代码总是使用注释,尤其是在团队环境中。
·对由循环和逻辑分支组成的代码使用注释。
这些是帮助源代码读者的主要方面。
·在整个应用程序中,使用具有一致的标点和结构的统一样式来构造注释。
·用空白将注释同注释分隔符分开。
在没有颜色提示的情况下查看注释时,这样做会使注释很明显且容易被找到。
C#编码标准--编码习惯
1.避免将多个类放在一个文件里面。
2.一个文件应该只有一个命名空间,避免将多个命名空间放在同一个文件里面。
3.一个文件最好不要超过500行的代码(不包括机器产生的代码)。
4.一个方法的代码长度最好不要超过25行。
5.避免方法中有超过5个参数的情况。
使用结构来传递多个参数。
6.每行代码不要超过80个字符。
7.不要手工的修改机器产生的代码。
a)如果需要编辑机器产生的代码,编辑格式和风格要符合该编码标准。
b)Usepartialclasseswheneverpossibletofactoroutthemaintainedportions.
8.避免利用注释解释显而易见的代码。
a)代码应该可以自解释。
好的代码由可读的变量和方法命名因此不需要注释。
9.Documentonlyoperationalassumptions,algorithminsightsandsoon.
10.避免使用方法级的文档。
a)使用扩展的API文档说明之。
b)只有在该方法需要被其他的开发者使用的时候才使用方法级的注释。
(在C#中就是///)
11.不要硬编码数字的值,总是使用构造函数设定其值。
12.只有是自然结构才能直接使用const,比如一个星期的天数。
13.避免在只读的变量上使用const。
如果想实现只读,可以直接使用readonly。
publicclassMyClass
{
publicreadonlyintNumber;
publicMyClass(intsomeValue)
{
Number=someValue;
}
publicconstintDaysInWeek=7;
}
14.每个假设必须使用Assert检查
a)平均每15行要有一次检查(Assert)
usingSystem.Diagnostics;
objectGetObject()
{…}
objectobj=GetObject();
Debug.Assert(obj!
=null);
15.代码的每一行都应该通过白盒方式的测试。
16.只抛出已经显示处理的异常。
17.在捕获(catch)语句的抛出异常子句中(throw),总是抛出原始异常维护原始错误的堆栈分配。
catch(Exceptionexception)
{
MessageBox.Show(exception.Message);
throw;//和throwexception一样。
}
18.避免方法的返回值是错误代码。
19.尽量避免定义自定义异常类。
20.当需要定义自定义的异常时:
a)自定义异常要继承于ApplicationException。
b)提供自定义的序列化功能。
21.避免在单个程序集里使用多个Main方法。
22.只对外公布必要的操作,其他的则为internal。
23.Avoidfriendassemblies,asitincreasesinter-assemblycoupling.
24.Avoidcodethatreliesonanassemblyrunningfromaparticularlocation.
25.使应用程序集尽量为最小化代码(EXE客户程序)。
使用类库来替换包含的商务逻辑。
26.避免给枚举变量提供显式的值。
//正确方法
publicenumColor
{
Red,Green,Blue
}
//避免
publicenumColor
{
Red=1,Green=2,Blue=3
}
27.避免指定特殊类型的枚举变量。
//避免
publicenumColor:
long
{
Red,Green,Blue
}
28.即使if语句只有一句,也要将if语句的内容用大括号扩起来。
29.避免使用trinary条件操作符。
30.避免在条件语句中调用返回bool值的函数。
可以使用局部变量并检查这些局部变量。
boolIsEverythingOK()
{…}
//避免
if(IsEverythingOK())
{…}
//替换方案
boolok=IsEverythingOK();
if(ok)
{…}
31.总是使用基于0开始的数组。
32.在循环中总是显式的初始化引用类型的数组。
publicclassMyClass
{}
MyClass[]array=newMyClass[100];
for(intindex=0;index{
array[index]=newMyClass();
}
33.不要提供public和protected的成员变量,使用属性代替他们。
34.避免在继承中使用new而使用override替换。
35.在不是sealed的类中总是将public和protected的方法标记成virtual的。
36.除非使用interop(COM+或其他的dll)代码否则不要使用不安全的代码(unsafecode)。
37.避免显示的转换,使用as操作符进行兼容类型的转换。
Dogdog=newGermanShepherd();
GermanShepherdshepherd=dogasGermanShepherd;
if(shepherd!
=null)
{…}
38.当类成员包括委托的时候
a)Copyadelegatetoalocalvariablebeforepublishingtoavoidconcurrencyrace
condition.
b)在调用委托之前一定要检查它是否为null
publicclassMySource
{
publiceventEventHandlerMyEvent;
publicvoidFireEvent()
{
EventHandlertemp=MyEvent;
if(temp!
=null)
{
temp(this,EventArgs.Empty);
}
}
}
39.不要提供公共的事件成员变量,使用事件访问器替换这些变量。
publicclassMySource
{
MyDelegatem_SomeEvent;
publiceventMyDelegateSomeEvent
{
add
{
m_SomeEvent+=value;
}
remove
{
m_SomeEvent-=value;
}
}
}
40.使用一个事件帮助类来公布事件的定义。
41.总是使用接口。
42.类和接口中的方法和属性至少为2:
1的比例。
43.避免一个接口中只有一个成员。
44.尽量使每个接口中包含3-5个成员。
45.接口中的成员不应该超过20个。
a)实际情况可能限制为12个
46.避免接口成员中包含事件。
47.避免使用抽象方法而使用接口替换。
48.在类层次中显示接口。
49.推荐使用显式的接口实现。
50.从不假设一个类型兼容一个接口。
Defensivelyqueryforthatinterface.
SomeTypeobj1;
IMyInterfaceobj2;
/*假设已有代码初始化过obj1,接下来*/
obj2=obj1asIMyInterface;
if(obj2!
=null)
{
obj2.Method1();
}
else
{
//处理错误
}
51.表现给最终用户的字符串不要使用硬编码而要使用资源文件替换之。
52.不要硬编码可能更改的基于配置的字符串,比如连接字符串。
53.当需要构建长的字符串的时候,使用StringBuilder不要使用string
54.避免在结构里面提供方法。
a)建议使用参数化构造函数
b)可以重裁操作符
55.总是要给静态变量提供静态构造函数。
56.能使用早期绑定就不要使用后期绑定。
57.使用应用程序的日志和跟踪。
58.除非在不完全的switch语句中否则不要使用goto语句。
59.在switch语句中总是要有default子句来显示信息(Assert)。
intnumber=SomeMethod();
switch(number)
{
case1:
Trace.WriteLine("Case1:
");
break;
case2:
Trace.WriteLine("Case2:
");
break;
default:
Debug.Assert(false);
break;
}
60.除非在构造函数中调用其他构造函数否则不要使用this指针。
//正确使用this的例子
publicclassMyClass
{
publicMyClass(stringmessage)
{}
publicMyClass():
this("hello")
{}
}
61.除非你想重写子类中存在名称冲突的成员或者调用基类的构造函数否则不要使用base来访问基类的成员。
//正确使用base的例子
publicclassDog
{
publicDog(stringname)
{}
virtualpublicvoidBark(inthowLong)
{}
}
publicclassGermanShepherd:
Dog
{
publicGermanShepherd(stringname):
base(name)
{}
overridepublicvoidBark(inthowLong)
{
base.Bark(howLong);
}
}
62.基于模板的时候要实现Dispose()和Finalize()两个方法。
63.通常情况下避免有从System.Object转换来和由System.Object转换去的代码,而使用强制转换或者as操作符替换。
classSomeClass
{}
//避免:
classMyClass
{
voidSomeMethod(Tt)
{
objecttemp=t;
SomeClassobj=(SomeClass)temp;
}
}
//正确:
classMyClasswhereT:
SomeClass
{
voidSomeMethod(Tt)
{
SomeClassobj=t;
}
}
64.在一般情况下不要定影有限制符的接口。
接口的限制级别通常可以用强类型来替换之。
publicclassCustomer
{…}
//避免