轻灵自由的珍珠

一个程序应该是轻灵自由的,它的子过程就象串在一根线上的珍珠。自始至终,目标明确。既没有不必要的循环也没有没有被引用的变量,既不缺少结构化也不至于僵硬呆板。

转载 C#编码规范收藏

新一篇: for和foreach的选择 | 旧一篇: DataSource与一维数组的绑定

1.  避免将多个类放在一个文件里面。

2.  一个文件应该只有一个命名空间,避免将多个命名空间放在同一个文件里面。

3.  一个文件最好不要超过500行的代码(不包括IDE产生的代码)。

4.  一个方法的代码长度最好不要超过25行。

5.  避免方法中有超过5个参数的情况。如果超过了,则应使用 struct 来传递多个参数。

6.  每行代码不要超过80个字符。

7.  原则上,尽量不要手工的修改机器产生的代码。

a)  如果需要编辑机器(IDE)产生的代码,编辑格式和风格要符合该编码标准。

b)  尽可能地使用片断类来把被保持的部分分解为各个因素

    注:这里的翻译参考了灵感之源老兄的说法,在Visual c#2005中,C#的语法已经支持partial修饰符,它的作用是可以将一个完整的类分解各个部分类,在编译时,编译器会将它们构造为一个类。

8.  避免利用注释解释显而易见的代码。

a)  代码应该可以自解释。好的代码本身就应具体良好的可读性,所使用的变量和方法命名一般情况下不需要注释。

9.  文档应该仅用于assumptions, algorithm insights等等.

10.  避免使用方法级的文档。

a)  使用扩展的API文档进行说明。

b)  只有在该方法需要被其他的开发者使用的时候才使用方法级的注释。(在C#中就是///

11.  不要硬编码数字的值,总是使用构造函数设定其值。

12.  只有是自然结构才能直接使用const(常量),比如一个星期的天数。

13.  区别只读变量及常量的使用方法,如果想实现只读变量,可以直接使用readonly 修饰符

public class MyClass

{

   public readonly int Number;

   public MyClass(int  someValue)

   {

      Number = someValue;

   }

   public  const int  DaysInWeek = 7;

}

14.  每个假设必须使用Assert检查

a)  平均每15行要有一次检查(Assert)

using System.Diagnostics;

    object GetObject()

{…}

    object obj = GetObject();

Debug.Assert(obj != null);

15.  代码的每一行都应该通过白盒方式的测试。

16.  只抛出已经显示处理的异常。

17.  在捕获(catch)语句的抛出异常子句中(throw),总是抛出原始异常,用以维护原始错误的堆栈分配。   catch(Exception exception)

{   

      MessageBox.Show(exception.Message);

      throw ;  //throw exception一样。

}

  注:同理,不推荐在循环语句中,进行直接的return操作。     for (int i=0;i<100;i++)     {         if (i==10)         {             return; //不推荐的方式         }     } 18.  避免方法的返回值是错误代码。

19.  尽量避免定义自定义异常类。

20.  当需要定义自定义的异常时:

a)  自定义异常要继承于ApplicationException

b)  提供自定义的序列化功能。

21.  避免在单个程序集里使用多个Main方法。

22.  只对外公布必要的操作,其他的则为internal

23.  避免使用友元程序集,因为它会增加程序集间的耦合度。

24.  避免编写从指定的位置加载的程序集的代码。

25.  使应用程序集尽量为最小化代码(EXE客户程序)。使用类库来替换包含的商务逻辑。

26.  避免给枚举变量提供显式的值。

//正确方法 

public enum Color

{   

   Red,Green,Blue

}

//避免

public enum Color

{   

   Red = 1,Green =  2,Blue = 3

}

27.  避免指定特殊类型的枚举变量。

//避免 

public enum Color  : long

{   

   Red,Green,Blue

}

28.  即使if语句只有一句,也要将if语句的内容用大括号扩起来。

29.  避免使用trinary条件操作符。

30.  避免在条件语句中调用返回bool值的函数。可以使用局部变量并检查这些局部变量。

bool IsEverythingOK()

{…}

//避免

if (IsEverythingOK ())

{…}

//替换方案 

bool ok = IsEverythingOK();

if (ok)

{…}

31.  总是使用基于0开始的数组。

32.  在循环中总是显式的初始化引用类型的数组。

public class MyClass

{}

MyClass[] array = new  MyClass[100];

for(int index = 0; index < array.Length;  index++)

{

   array[index] = new  MyClass();

}

33.  尽量不要提供public protected的成员变量,使用属性代替他们。

34.  避免在继承中使用new而使用override来进行替换。

35.  在不是sealed的类中总是将public protected的方法标记成virtual的。

36.  除非使用interop(COM+ 或其他的dll)代码否则不要使用不安全的代码(unsafe code)

37.  避免显式的转换,使用as操作符进行兼容类型的转换。

Dog dog = new GermanShepherd();

GermanShepherd shepherd = dog  as  GermanShepherd;

if (shepherd != null )

{…}

38.  当类成员包括委托的时候

a)  在调用委托前,将它拷贝到一个本地变量中,用以避免并发争用条件。

b)  在调用委托之前一定要检查它是否为null

public class MySource

{

   public event EventHandler  MyEvent;

   public void FireEvent()

   {     //将委托拷到一个本地变量中。       EventHandler temp = MyEvent;       //确定它是否为空        if(temp != null )

      {

         temp(this,EventArgs.Empty);

      }

   }

}  

39.  不要提供公共的事件成员变量,使用事件访问器替换这些变量。

public class MySource

{

   MyDelegate m_SomeEvent ;

   public event MyDelegate SomeEvent

   {

      add

      {

         m_SomeEvent += value;

      }

      remove

      {

         m_SomeEvent -= value;

      }

   }

}

40.  使用一个事件帮助类来公布事件的定义。

41.  总是使用接口。

42.  类和接口中的方法和属性至少为2:1的比例。

43.  避免一个接口中只有一个成员。

44.  尽量使每个接口中包含35个成员。

45.  接口中的成员不应该超过20个。

a) 根据实际情况可能限制为12

46.  避免接口成员中包含事件。

47.  避免使用抽象方法而使用接口替换。

48.  在类层次中显示接口。

49.  推荐使用显式的接口实现。

50.  从不假设一个类型兼容一个接口,并应防止查询那些接口。

SomeType obj1;

IMyInterface obj2;

 

/* 假设已有代码初始化过obj1,接下来 */

obj2 = obj1 as IMyInterface;

if (obj2 != null)

{

   obj2.Method1();

}

else

{

   //处理错误

}  

51. 表现给最终用户的字符串(一般指UI界面中的部分)不要使用直接编码,而应该要使用资源文件来替换。

          注:这样做的目的是方便软件的本地化。

52.