C#程式設計好習慣

笨笨鼠→_→發表於2012-07-06

1.  避免將多個類放在一個檔案裡面。

2.  一個檔案應該只有一個名稱空間,避免將多個名稱空間放在同一個檔案裡面。

3.  一個檔案最好不要超過500行的程式碼(不包括機器產生的程式碼)。

4.  一個方法的程式碼長度最好不要超過25行。

5.  避免方法中有超過5個引數的情況。使用結構來傳遞多個引數。

6.  每行程式碼不要超過80個字元。

7.  不要手工的修改機器產生的程式碼。

a)  如果需要編輯機器產生的程式碼,編輯格式和風格要符合該編碼標準。

b)  Use partial classes whenever possible to factor out the maintained portions.

8.  避免利用註釋解釋顯而易見的程式碼。

a)  程式碼應該可以自解釋。好的程式碼由可讀的變數和方法命名因此不需要註釋。

9.  Document only operational assumptions, algorithm insights and so on.  

10.  避免使用方法級的文件。

a)  使用擴充套件的API文件說明之。

b)  只有在該方法需要被其他的開發者使用的時候才使用方法級的註釋。(在C#中就是///)

11.  不要硬編碼數字的值,總是使用建構函式設定其值。

12.  只有是自然結構才能直接使用const,比如一個星期的天數。

13.  避免在只讀的變數上使用const。如果想實現只讀,可以直接使用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一樣。

}

18.  避免方法的返回值是錯誤程式碼。

19.  儘量避免定義自定義異常類。

20.  當需要定義自定義的異常時:

a)  自定義異常要繼承於ApplicationException。

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

21.  避免在單個程式集裡使用多個Main方法。

22.  只對外公佈必要的操作,其他的則為internal。

23.  Avoid friend assemblies, as it increases inter-assembly coupling.

24.  Avoid code that relies on an assembly running from a particular location.

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)  Copy a delegate to a local variable before publishing to avoid concurrency race

condition. 

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.  儘量使每個介面中包含3-5個成員。

45.  介面中的成員不應該超過20個。

a)  實際情況可能限制為12個

46.  避免介面成員中包含事件。

47.  避免使用抽象方法而使用介面替換。

48.  在類層次中顯示介面。

49.  推薦使用顯式的介面實現。

50.  從不假設一個型別相容一個介面。Defensively query for that interface.

SomeType obj1;

IMyInterface obj2;

 

/* 假設已有程式碼初始化過obj1,接下來 */

obj2 = obj1 as IMyInterface;

if (obj2 != null)

{

   obj2.Method1();

}

else

{

   //處理錯誤

}  

51.  表現給終端使用者的字串不要使用硬編碼而要使用資原始檔替換之。

52.  不要硬編碼可能更改的基於配置的字串,比如連線字串。

53.  當需要構建長的字串的時候,使用StringBuilder不要使用string

54.  避免在結構裡面提供方法。

a)  建議使用引數化建構函式

b)  可以重裁操作符

55.  總是要給靜態變數提供靜態建構函式。

56.  能使用早期繫結就不要使用後期繫結。

57.  使用應用程式的日誌和跟蹤。

58.  除非在不完全的switch語句中否則不要使用goto語句。

59.  在switch語句中總是要有default子句來顯示資訊(Assert)。

int number  = SomeMethod();

switch(number)

{

   case 1:

      Trace.WriteLine("Case 1:");

      break;

   case 2:

      Trace.WriteLine("Case 2:");

      break;

   default :

      Debug.Assert(false);

      break;

}

60.  除非在建構函式中呼叫其他建構函式否則不要使用this指標。

// 正確使用this的例子

public class MyClass

{

   public MyClass(string message )

   {}

   public MyClass()  : this("hello")

   {}

}

61.  除非你想重寫子類中存在名稱衝突的成員或者呼叫基類的建構函式否則不要使用base來訪問基類的成員。

// 正確使用base的例子

public class Dog

{

   public Dog(string name)

   {}

   virtual public void Bark( int howLong)

   {}

}

public class GermanShepherd : Dog

{

   public GermanShe pherd(string name): base (name)

   {}

   override public void Bark(int  howLong) 

   {

      base .Bark(howLong);  

   }

}

62.  基於模板的時候要實現Dispose()和Finalize()兩個方法。

63.  通常情況下避免有從System.Object轉換來和由System.Object轉換去的程式碼,而使用強制轉換或者as操作符替換。

class SomeClass

{}

//避免:

class MyClass<T> 

{   

   void SomeMethod(T t)   

   {

      object temp = t;      

      SomeClass obj = (SomeClass)temp;    

   }

}

// 正確:

class MyClass<T> where T : SomeClass

{   

   void SomeMethod(T t)   

   {

      SomeClass obj = t;   

   }

}

64.  在一般情況下不要定影有限制符的介面。介面的限制級別通常可以用強型別來替換之。

public class Customer

{…}

//避免:

public interface IList<T> where T : Customer 

{…}

//正確:

public interface ICustomerList : IList<Customer> 

{…}

65.  不確定在介面內的具體方法的限制條件。

66.  總是選擇使用C#內建(一般的generics)的資料結構。

 

相關文章