C#编码规范

来源:互联网 发布:农村信用社软件下载 编辑:程序博客网 时间:2024/05/25 05:37

1          关于C#编码规范

这个文档可以作为一个向导,以写强壮可靠的程序。虽然这里关注的是用C#写程序,但如果使用另外一种编程语言,很多规则和原理也是有用的。

2          文件组织

2.1      C#源文件

把每个类都放在单独的文件中,文件名字和类名一致(用.CS作为扩展名)。类文件不要太长,不要超过2000LOC。必要时,分割代码,使结构更清晰。

2.2      目录安排

为每个命名空间创建一个目录(如,对于MyProject.TestSuite.TestTier使用MyProject/TestSuite/TestTier作为路径,不要使用带“.”的命名空间)。这样更易于映射命名空间到目录。

3          缩进

3.1      分行

如果表达式不适合单行显示,应根据下面通常的原则分行:

n         在一个逗号后换行

n         在一个操作符后换行

n         在表达式的高层次处换行

n         新行与前一行在同一层次,并与表达式的起始对齐

方法分行的例子:

long MethodCall(expr1, expr2,

                        expr3, expr4, expr5);

算术表达式分行的例子:

好的:

       var = a * b / (c – g + f) +

               4 * z;

坏的风格,要避免:

       var = a * b / (c – g +

               f) + 4 * z;

第一个是好的,因为分行符合高层次规则。

3.2      空白

不要使用空格缩进 使用tabs

4          注释

4.1      块注释

通常要避免块注释,而使用C#标准的///注释来描述。如果希望使用块注释,应该使用下面的风格:

/ * Line 1

  * Line 2

  * Line 3

  */

块注释很少使用,通常是用来注释掉大块的代码。

4.2      单行注释

应该使用//注释掉一行代码,也可以用它注释掉代码块。当单行注释用来做代码解释时,必须要缩进到与代码对齐。

4.3      文档注释

单行XML注释的形式如下:

/// <summary>

/// This class…

/// </summary>

多行XML注释的形式如下:

/// <exception cref=”BogusException”>

/// This exception gets thrown as soon as a

/// Bogus flag gets set.

/// </exception>

5          声明

5.1      每行声明的数量

建议每行只有一个声明,还方便注释,如:

int level;  // indentation level

int size;   // size of table

变量的命名意义要明确。如果能够自解释,如indentLevel,就不用注释。

不好的:

int a, b; // What is ‘a’? What does ‘b’ stand for?

5.2      初始化

尽量在局部变量声明时进行初始化,例如:

string name = myObject.Name;

int val = time.Hours;

注意:初始化对话框时,尽量使用语句:

Using (OpenFileDialog openFileDialog = new OpenFileDialog())

{

       ……

}

5.3      类和接口的声明

当写C#类和接口时,应按照下面的格式规则:

n         在方法名字和参数列表的起始括号“(”之间没有空格

n         开括号“{”应出现在声明语句之后的下一行

n         闭括号“}”自己占一行,并缩进到对应的开括号位置

例如:

class MySample : MyClass, IMyInterface

{

int myInt;

 

public MySample(int myInt)

{

       this.myInt = myInt;

}

 

void Inc()

{

       ++myInt;

}

 

void EmptyMethod()

{

}

}

6          语句

6.1      简单语句

每行应该只包含一个语句。

6.2      返回语句

返回语句不应该带有最外面的括号。

不应该使用:

return (n * (n + 1) / 2);

应该使用:

return n * (n + 1) / 2;

6.3      If, if - else, if else - if else语句

if, if – elseif else – if else语句应该按照下面格式:

if (condition)

{

       ……

}

 

if (condition)

{

       ……

}

else

{

       ……

}

 

if (condition)

{

    ……

}

else if (condition)

{

    ……

}

else

{

    ……

}

注意:即使某条件下只有一个语句,也要使用大括号“{”“}”。后面的循环等语句也一样。

6.4      for / foreach语句

for语句形式如下:

for (int i = 0; i < 5; ++i)

{

    ……

}

或者使用单行形式:

for (initialization; condition; updat);

单行形式可考虑使用while语句代替。

foreach语句如下:

foreach (int i in intList)

{

    ……

}

6.5      while / do – while语句

while语句如下:

while (condition)

{

    ……

}

空的while语句形式如下:

while (condition);

do – while语句如下:

do

{

    ……

}

while (condition);

6.6      switch语句

switch语句形式如下:

switch (condition)

{

    case A :

           ……

           break;

    case B :

           ……

           break;

    default :

           ……

           break;

}

6.7      try – catch语句

try – catch语句形式如下:

try

{

    ……

}

catch (Exception e)

{

    ……

}

或者

try

{

    ……

}

catch (Exception e)

{

    ……

}

finally

{

    ……

}

6.8      属性

属性形式如下:

public string Name

{

    get

      {

              ……

      }

      set

      {

              ……

      }

}

对于抽象属性:

public string Name

{

    get;

    set;

}

6.9      枚举

枚举形式如下:

public enum Color

{

    Red,

    Green,

    Blue

}

7          空白

7.1      空行

使用空行按照逻辑关系分隔代码,能提高可读性。

在下面元素之间要使用一个空行:

n         构造函数

n         属性

n         方法

n         方法内的逻辑块

7.2      内部空格

在逗号或分号之后应该有一个空格,例如:

应该使用:

       TestMethod(a, b, c);

不应该使用:

       TestMethod(a,b,c);或者TestMethod( a, b, c );

操作符两边要有一个空格(递增和逻辑否等一元操作符除外),例如:

应该使用:

       a = b;

不应该使用:

       a=b;

应该使用:

       for (int i = 0; i < 10; ++i)

不应该使用:

       for (int i=0; i<10; ++i)或者for(int i=0;i<10;++i)

7.3      制表格式

行逻辑块应该写成类似表格格式:

string   name         = “Mr. Ed”;

int       myValue     = 5;

Test     aTest         = Test.TestYou;

8          命名约定

8.1      大写风格

8.1.1        Pascal风格

大写每一个单词的第一个字符,如TestCounter

8.1.2        Camel风格

除了第一个单词,大写其它单词的第一个字符,如testCounter

8.1.3        全部大写

如果一个标志符是只包含123个字符的缩写,可以全部大写,例如:

public class Math

{

    public const double PI = ......

}

8.2      命名规则

.Net中,通常认为使用下划线和匈牙利符号命名是不好的。

匈牙利符号定义了一组名字的前缀和后缀,来表示变量的类型。这种命名风格在早期的windows编程中广泛使用。在MFC编程中,还习惯使用m_作为成员变量的前缀。这些风格在.Net中不应该使用。记住:一个好的变量名字应该描述语义,而不是类型。

GUI代码是个例外。所有GUI元素类型(如Button)的域和变量名字,应该以它的类型全名作为后缀,例如:

System.Windows.Forms.Button       cancelButton;

System.Windows.Forms.TextBox      nameTextBox;

8.2.1        classstructnamespace命名规则

n         名字必须是名词或名词短语

n         异常类要以Exception作为后缀

n         不要使用任何前缀

n         使用Pascal风格

8.2.2        interface命名规则

n         用名词,名词短语或者描述行为的形容词命名接口。(如IComponentIEnumbetable

n         使用Pascal风格

n         使用I作为名字的前缀,I后面的字符(接口名字的第一个字符)要大写

8.2.3        enum命名规则

n         枚举类型名和值的名字都使用Pascal风格

n         枚举类型和值都没有前缀和后缀

8.2.4        域命名规则

n         使用描述性的名字,能充分表示出变量的含义

n         对于静态的readonlyconst域,用名词,名词短语或名词缩写命名

n         public域使用Pascal风格

n         protectedprivate域使用Camel风格

8.2.5        参数命名规则

n         使用描述性的名字,能充分表示出变量的含义

n         使用Camel风格

8.2.6        变量命名规则

n         尽量使用含义明确的名字

n         如果变量仅用来在循环中计数,应优先使用ijklmn

n         使用Camel风格

8.2.7        方法命名规则

n         用动词或动词短语命名

n         使用Pascal风格

8.2.8        属性命名规则

n         使用名词或名词短语命名

n         使用Pascal风格

8.2.9        事件命名规则

n         事件控制器要带有EventHandler后缀

n         使用sendere命名两个参数

n         事件参数类要带有EventArgs后缀

n         考虑使用动词命名事件

n         对于有“之前”或“之后”概念的事件,要使用现在时或过去时命名

n         使用Pascal风格

9          编程实践

9.1      书写顺序

书写类时,按照从上到下的顺序,类成员应该是域,构造函数,属性,方法。

9.2      成员可视性

类的域都应该是private,如果需要被外部访问,使用public属性进行访问。但也有例外:

n         如果类的域仅作为一种数据集合,可以将域设定为public,这样的类不要有任何方法

n         常量域,静态域或静态常量域可以设定为public

private是默认的类成员访问修饰符,可以省略,但为了明确表达,应该书写出来。

9.3      功能单一

类的功能要单一,不要组合没有直接关联的功能。方法也一样。一个方法只完成一个任务,不要把多个任务组合进一个方法,即使那些任务很小。就是说,应该以逻辑功能来界分类或方法。

9.4      使用枚举

不要使用数字或字符串来指示离散值,应该使用枚举。

不好的:

void SendMail(string message, string mailType)

{

switch (mailType)

{

case "Html" :

        ……

        break;

case "PlainText" :

        ……

        break;

case "Attachment" :

        ……

        break;

default :

        ……

        break;

}

}

好的:

enum MailType

{

        Html,

        PlainText,

        Attachment

}

 

void SendMail(string message, MailType mailType)

{

switch (mailType)

{

case MailType.Html :

        ……

        break;

case MailType.PlainText :

        ……

        break;

case MailType.Attachment :

        ……

        break;

default :

        ……

        break;

}

}

9.5      捕获异常

只捕获特定的异常,如读取外部文件,而不要捕获一般异常,有利于调试排错。

不要捕获了异常却什么也不错,应该做适当处理,并把结果反馈到界面。如果隐藏了一个异常,将很难知道异常到底发生了没有,或者在哪里发生的。