A.1 通用风格约定
A.1.1 花括号的使用
√ 要把左花括号放在前一条语句的末尾。
if (someExpression){
DoSomething();
}
√ 要使右花括号与左花括号所在行的行首对齐,除非花括号内只有一条语句。
if (someExpression){
DoSomething();
}
√ 要把右花括号放在新的一行的开始处。
if (someExpression) {
DoSomething();
}
√ 考虑把只有一条语句的代码块和左右花括号写在同一行中。属性的访问方法经常使用这种风格。
public int Foo{
get{ return foo; }
set{ foo=value; }
}
√ 考虑把只有一个访问方法的属性的所有花括号写在同一行中。
public int Foo{ get{ return foo; } }
√ 要使右花括号单独占一行,除非它后面是else、else if或while。
if (someExpression){
do{
DoSomething();
} while(someOtherCondition);
}
× 避免省略花括号,即便编程语言允许这样做。
不应该认为花括号是可以省略的。即使是对只有一条语句的代码块,仍应该使用花括号。这样可以增加代码的可读性和可维护性。
for (int i=0;i<100;i++){ DoSomething(i); }
只有在极少数情况下才可以省略花括号,比如在原来仅有的一条语句后再添加新的语句是不可能的或是非常罕见的。例如,在throw语句后再添加任何语句都是没有意义的:
if(someExpression) throw new ArgumentOutOfRangeException(…);
本条约定的另一个例外是case语句。由于case和break语句已经表示了代码块的起始和结束,因此这些花括号可以被省略。
case 0;
Dosomething();
break;
A.1.2 空格的使用
√ 要在左花括号之后和右花括号之间加一个空格。
public int Foo{ get{ return foo; } }
× 避免在左花括号之前加空格。
最好如此: if(someExpression){
可以接受: if(someExpression) {
√ 要在形式参数之间的逗号后加一个空格。
正确:public void Foo(char bar, int x, int y)
错误:public void Foo(char bar,int x,int y)
× 避免在实际参数加空格。
最好如此:Foo(myChar,0,1)
可以接受:Foo(myChar, 0, 1)
× 避免在左圆括号之后或右圆括号之前加空格。
最好如此:Foo(myChar,0,1)
可以接受:Foo( myChar, 0, 1 )
× 不要在成员的名字和左圆括号之前加空格。
正确:Foo()
错误:Foo ()
× 不要在左方括号之后或右方括号之前加空格。
正确:x=dataArray[index];
错误:x=dataArray[ index ];
× 不要在控制流语句之前加空格。
正确:while(x==y)
错误:while (x==y)
× 避免在二元操作符之前和之后加空格。
最好如此:if(x==y){ … }
可以接受:if(x == y){ … }
× 不要在一元操作符之前或之后加空格。
正确:if(!y){ … }
错误:if(! y){ … }
A.1.3 缩进的使用
√ 要用四个连续的空格符来进行缩进。
× 不要用制表符(tab)来进行缩进。
√ 要对代码块中的内容进行缩进。
if(someExpression){
DoSomething();
}
√ 要对case代码块进行缩进,尽管没有使用花括号。
switch(someExpression){
case 0:
DoSomething();
break;
…
}
A.2 命名约定
总的来说,我们建议遵循《框架设计准则》中的命名规范。但是,在命名内部标识符和私有标识符时,存在一些例外,需要另外一些约定。
√ 要在命名标识符时遵循《框架设计准则》中的命名规范,除非是内部字段和私有字段。
√ 要在命名名字空间、类型及成员时采用PascalCasing大小写风格,除非是内部字段和私有字段。
√ 要用camelCasing大小写风格来命名内部字段和私有字段。
√ 要用camelCasing大小写风格来命名局部变量。
√ 要用camelCasing大小写风格来命名方法的形式参数。
× 不要使用匈牙利命名法(也就是说,不要载变量名中包含变量的类型)。
× 避免给局部变量加前缀。
√ 要使用C#语言中对应的别名,不要使用.NET框架中的类型名。
例如:要使用int而不是Int32,要使用object而不是Object。
A.3 注释
应该用注释来描述代码的用意、大治的算法以及逻辑流程。最好的情况是,代码编写者之外的人能够通过独自阅读注释来理解函数的行为和目的。虽然注释并不存在一个最低标准,而且一些非常短小的函数根本不需要注释,但对大多数函数来说,通过注释来放映程序员的意图和所采用的方法仍然是值得的。
× 不要用注释来描述一些对任何人都显而易见的事。
× 避免使用块注释(/*…*/)。即使注释会有多行,也最好是使用单行注释语法(//…)。
// Implements a variable-size list that uses an array of objects
// to store the elements. A List has a capacity, which is the
// allocated length of the internal array. As elements are added
// to a List, the capacity of the List is automatically increased
// as required by reallocating the internal array.
//
public class List<T>:IList<T>,IList{
…
}
× 不要把注释放在行尾,除非注释非常短。
//Avoid
public class ArrayList{
private int count; // -1 indicates uninitialized array
}
A.4文件的组织
× 不要在一个源文件中包含一个以上的共用类型,除非有嵌套类,或各类型之间的不同之处仅在于泛型参数的数量。
一个文件中有多个内部类型是允许的。
√ 要用相同的名字来命名源文件及其包含的公用类型。
例如,String类应该在String.cs文件中,而List<T>类则应该在List.cs文件中。
√ 要用相同的层次结构来组织文件目录和名字空间。
例如,应该把System.Collections.Generic.List<T>的源文件放在System\Collections\Generic目录中。
√ 考虑根据下面给出的顺序和组别来对成员进行分组:
l 所有字段.
l 所有构造函数.
l 公有属性及受保护的属性.
l 方法.
l 事件.
l 所有显式实现的借口成员.
l 内部成员.
l 私有成员.
l 所有嵌套类型.
√ 要把不能公开访问的成员和显式实现的接口成员分别放在自己的#region块中。
#region internal members
…
#endregion
#region private members
…
#endregion
√ 考虑在每个组别内根据字母顺序来组织成员。
√ 考虑根据由简单到复杂的顺序来组织重载成员。
√ 要把using指令放在名字空间的声明之外。
using System;
namespace System.Collections{
…
}