天天看點

C#代碼規範 .NET程式員需要提升的修養

1. 引言

本文是一套面向C# programmer 和C# developer 進行開發所應遵循的開發規範。

按照此規範來開發C#程式可帶來以下益處:

· 代碼的編寫保持一緻性,

·         提高代碼的可讀性和可維護性,

·         在團隊開發一個項目的情況下,程式員之間可代碼共享

·         易于代碼的回顧,

本規範是初版,隻适用于一般情況的通用規範,并不能覆寫所有的情況。

2. 檔案組織

2.1 C# 源檔案

類名或檔案名要簡短,不要超過2000LOC,将代碼分割開,使結構清晰。将每個類放在一個單獨的檔案中,使用類名來命名檔案名(當然擴充名是.cs)。這種約定會使大家工作更簡單。

2.2 目錄設計

為每一個命名空間建立一個目錄。(用MyProject/TestSuite/TestTier作為MyProject.TestSuite.TestTier的路徑,而不用帶點的命名空間名做路徑)這樣可以更容易地将命名空間映射到目錄層次劃分。

3. 縮進

3.1 換行

當一個表達式超過一行時,根據這些通用原則進行處理:

·         在逗号後換行。

·         在操作符後換行。

·         在高層換行而不要在低層處換行。

·         折行後對齊上一行語句同一層的表達式起始位置。

方法調用換行示例:

longMethodCall(expr1, expr2,       expr3, expr4, expr5); 

算術表達式換行示例:

推薦:

var = a * b / (c - g + f) +        4 * z; 

不好的格式——應避免:

var = a * b / (c - g +        f) + 4 * z; 

推薦使用第一種方法,因為是在括号表達式之外折行(高層次折行原則)。注意要用制表符到縮進的位置,然後用用空格到折行的位置。在我們的例子中是:

> var = a * b / (c - g + f) +  > ......4 * z; 

'>'表示是制表符,'.'表示是空格符。(制表符後是空白是用制表符縮進)。一個好的編碼習慣就是在所用的編輯器中顯示制表符和空格符。

3.2 空白

利用空格進行縮進從未有過統一的标準。一些人喜歡用兩個空格,一些人喜歡用四個空格而還有一些人喜歡用八個空格,甚至有的人喜歡用更多的空格。好的做法是用制表符。制表符有一些優點:

·         每個人都可以設定他們自己喜歡的縮進層級。

·         它僅僅是1個字元而不是2,4,8等等,是以它将減少輸入(甚至因為自動縮進,有時你不得不手工設定縮進或取消設定,等等諸如此類的操作)。

·         如果你想增加或減少縮進,可以标記一塊,使用Tab增加縮進層級而用Shift-Tab減少縮進層級。這幾乎對于任何文本編輯器都是适用的。

這裡,我們定義制表符為标準縮進符。

不要用空格縮進—用制表符!

4. 注釋

4.1 塊注釋

塊注釋通常應該是被避免的。推薦使用///注釋作為C#的标準聲明。如果希望用塊注釋時你應該用以下風格:

/* Line 1  * Line 2  * Line 3  */ 

因為樣可以為讀者将注釋塊與代碼塊區分開。雖然并不提倡使用C風格的單行注釋,但你仍然可以使用。一旦用這種方式,那麼在注釋行後應有斷行,因為很難看清在同一行中前面有注釋的代碼:

/* blah blah blah */ 

塊注釋在極少情況下是有用的。通常塊注釋用于注釋掉大的代碼段。

4.2 單行注釋

你應該用//注釋風格“注釋掉”代碼(快捷鍵,Alt+/)。它也可以被用于代碼的注釋部分。

單行注釋被用于代碼說明時必須縮進到相應的編進層級。注釋掉的代碼應該放在第一行被注釋掉以使注釋掉的代碼更容易看清。

一條經驗,注釋的長度不應該超過被解釋代碼的長度太長,因為這表示代碼過于複雜,有潛在的bug。

4.3 檔案注釋

在.net 架構,Microsoft 已經介紹了一個基于XML 注釋的檔案。這些檔案是包括XML 标簽的正規的單行的C#注釋。他們遵循單行注釋的模式:

/// <summary>  /// This class...  /// </summary> 

多行XML 注釋遵循這種模式:

/// <exception cref=”BogusException”>  /// This exception gets thrown as soon as a  /// Bogus flag gets set.  /// </exception> 

為了被認作是XML注釋行,所有的行都必須用三個反斜線開始。标簽有以下兩類:

·         檔案說明項

·         格式/參考

第一類包括像<summary>, <param> or <exception>的标簽。描述一個程式的API元素的這些文檔說明項必須寫清楚以友善其他程式員。如上面的多行注釋示例所示,這些标簽通常帶有名稱或cref屬性。編譯器會檢查這些屬性,是以它們必須是有效、正确的。第二類用諸如<code>, <list> or <para>标簽,用于控制備注說明的布局。

檔案可以用‘檔案’菜單中的‘建立’菜單産生。檔案以HTML格式産生。

5. 聲明

5.1 每行的聲明數

推薦每行隻有一個聲明,因為它可以友善注釋。

int level; // indentation level  int size; // size of table 

當聲明變量時,不要把多個變量或不同類型的變量放在同一行,例如:

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

上面的例子也顯示了變量名不明顯的缺陷。當命名變量時要清晰。

5.2 初始化

局部變量一旦被聲明就要初始化。例如:

string name = myObject.Name; 

int val = time.Hours; 

注意:如果你初始化一個dialog,設計使用using語句:

using (OpenFileDialog openFileDialog = new OpenFileDialog()) {  ...  } 

5.3 類和接口聲明

當編寫C#類和接口時,應遵循以下格式化規則:

·         在方法名和圓括号“(”開始它的參數清單之間不要使用空格。

·         在聲明語句的下一行以大括号"{"标志開始。

·         以"}"結束,通過它自身的縮進與相應的開始标志比對。

例如:

Class MySample : MyClass, IMyInterface  {          int myInt;          public MySample(int myInt)          {          this.myInt = myInt ;          }          void Inc()         {                  ++myInt;          }          void EmptyMethod()          {          }  } 

對于一個大括号的位置參考10.1部分。

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-else and if else-if else 語句看起來應該像這樣:

if (condition) {  DoSomething();  ...  }  if (condition) {  DoSomething();  ...  } else {  DoSomethingOther();  ...  }  if (condition) {  DoSomething();  ...  } else if (condition) {  DoSomethingOther();  ...  } else {  DoSomethingOtherAgain();  ...  } 

6.4 for / foreach 語句

一個for語句應該如下形式:

for (int i = 0; i < 5; ++i) {  ...  } 

或者放置一行(考慮用一個while語句代替)

for (initialization; condition; update) ; 

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 statement語句應該遵循以下格式:

try {  ...  } catch (Exception) {}  or  try {  ...  } catch (Exception e) {  ...  }  or  try {  ...  } catch (Exception e) {  ...  } finally {  ...  } 

7. 空白

7.1 空行

空行提高可讀性。它們分開那些邏輯上自身相關聯的代碼塊。兩行空格行應該用于以下之間:

·         一個源檔案的邏輯段。

·         類和接口定義(每個檔案隻定義一個類或接口以避免這種情況)。

一個空格行應該總是被用于以下之間:

·         方法

·         屬性

·         一個方法中的局部變量和它的第一條語句

·         一個方法中的邏輯段為了提高可讀性。注意空白行必須被縮進因為它們包括一條語句這使得插入這些行更容易。

7.2 内部空格

在一個逗号或一個分号之後應該由一個空格,例如:

TestMethod(a, b, c); 不要用: TestMethod(a,b,c) 

TestMethod( a, b, c ); 

單個空格包圍操作符(除了像加的一進制操作符和邏輯非),例:

a = b; // don't use a=b;  for (int i = 0; i < 10; ++i) // don't use for (int i=0; i<10; ++i)  // or  // 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 Casing

習慣大寫每個單詞的第一個字母(就像在TestCounter)。

8.1.2 Camel Casing

習慣除了第一個單詞外大寫每個單詞的第一個字母例如testCounter。

8.1.3 全大寫情況

對于隻有一兩個字元縮寫組成的辨別符才用全大寫的情況。有三個或更多個字元組成的辨別符應該用Pascal情況代替。例如:

public class Math  {  public const PI = ...  public const E = ...  public const feigenBaumNumber = ...  } 

8.2. 命名指導方針

通常根據指導方針在名字和命名内用低線字元對Hungarian 符号來說被認為是壞習慣。

Hungarian 符号是一組應用于命名來映射變量類型的字首和字尾。這種命名風格在早期的Windows程式中被廣泛應用,但現在被取消了至少不提倡了。如果你遵循這個指南用Hungarian 符号是不允許的。

但要記住一個好的變量名描述了語義而不失類型。

對于這個規則有個例外就是GUI編碼。包括像按鈕(buttton)的GUI元素,所有領域和變量名都應該帶有它們類型名的字尾不是縮寫。例如:

System.Windows.Forms.Button cancelButton;  System.Windows.Forms.TextBox nameTextBox; 

8.2.1 類命名指導方針

·         類命名必須是名詞或名詞短語。

·         UsePascal 情況參考8.1.1

·         不要用任何類字首

8.2.2 接口命名指導方針Guidelines

·         用可以描述行為的名詞或名詞短語或形容詞命名接口。(例如IComponent 或 IEnumberable)

·         用Pascal情況(參考8.1.1)

·         用I作為名字的字首,它應該緊跟一個大寫字母(接口名的第一個字母)

8.2.3 枚舉命名指導方針

·         用Pascal情況命名枚舉值名字和類型名字

·         枚舉類型和枚舉值不要字首

·         對于枚舉用單一名字

·         對于位領域用複數名字

8.2.4 隻讀和常量命名

·         用名詞,名詞短語或名詞的縮寫命名靜态領域

·         使用Pascal 情況(參考8.1.1)

8.2.5 參數/非常量領域命名

·         一定要用描述性名字,應該能夠足夠表現變量的意義和它的類型。但一個好的名字應該基于參數的意義。

·         使用Camel情況(參考8.1.2)

8.2.6 變量命名

·         計數變量當用在瑣碎的計數循環式更适宜叫i, j, k, l, m, n。(參考10.2例如對全局計數的更智能命名等等)—

8.2.7 方法命名

·         用動詞或動詞短語命名方法。

·         使用Pascal(參考8.1.2)

8.2.8 屬性命名

·         用名詞或名詞短語命名屬性

·         使用Pascal 情況(參考8.1.2)

·         考慮用與其類型相同的名字命名一個屬性

8.2.9 事件命名

·         用事件處理器字尾命名事件處理器

·         用sender 和 e命名兩個參數

·         使用Pascal情況(參考8.1.1)

·         用EventArgs 字尾命名事件參數

·         用現在和過去時态命名有字首和複制概念的事件名字。

·         考慮用一個動詞命名事件。

8.2.10 大寫總結

Type

Case

Notes

Class / Struct

Pascal Casing

Interface

Starts with I

Enum values

Enum type

Events

Exception class

End with Exception

public Fields

Methods

Namespace

Property

Protected/private Fields

Camel Casing

Parameters

9. 程式設計習慣

9.1 可見性

不要任何公共執行個體或類變量,讓它們為私有的。對于私有成員最好不用“private”作修飾語什麼都不寫。私有是預設情況,每個C#程式員都應該知道這一點。

用屬性代替。你可以用公共靜态(或常量)對于這個規則是以例外,帶它不應該是規則。

9.2 沒有“幻”數

不要用幻數,也就是在源代碼中直接用常數值。替代這些後者以防變化(比方說,你的應用程式可以處理3540使用者代替427你的代碼在50行中通過分散25000LOC)是錯誤和沒有收益的。聲明一個帶有數的常量來代替:

public class MyMath  {  public const double PI = 3.14159...  } 

10. 編碼舉例

10.1 Brace placement example

namespace ShowMeTheBracket  {  public enum Test {  TestMe,  TestYou  }  public class TestMeClass  {  Test test;  public Test Test {  get {  return test;  }  set {  test = value;  }  }  void DoSomething()  {  if (test == Test.TestMe) {  //...stuff gets done  } else {  //...other stuff gets done  }  }  }  } 

括弧應該在以下情況之後以新行開始:

·         命名空間聲明(注意這在0.3版本中是新添的與0.2版本不同)

·         類/接口/結構聲明

·         方法聲明

10.2 變量命名舉例

代替:

for (int i = 1; i < num; ++i) {  meetsCriteria[i] = true;  }  for (int i = 2; i < num / 2; ++i) {  int j = i + i;  while (j <= num) {  meetsCriteria[j] = false;  j += i;  }  }  for (int i = 0; i < num; ++i) {  if (meetsCriteria[i]) {  Console.WriteLine(i + " meets criteria");  }  }  try intelligent naming :  for (int primeCandidate = 1; primeCandidate < num; ++primeCandidate)  {  isPrime[primeCandidate] = true;  }  for (int factor = 2; factor < num / 2; ++factor) {  int factorableNumber = factor + factor;  while (factorableNumber <= num) {  isPrime[factorableNumber] = false;  factorableNumber += factor;  }  }  for (int primeCandidate = 0; primeCandidate < num; ++primeCandidate)  {  if (isPrime[primeCandidate]) {  Console.WriteLine(primeCandidate + " is prime.");  }  } 

注意:索引變量通常叫i, j, k 等等。但Note: Indexer variables generally should be called i, j, k etc. But 萬一像這樣,使得重新考慮這個原則更有意義。一般來說,當同一個計數器或索引器被重用,給它們有意義的名字。

原文标題:C#代碼規範 程式員必備的秘笈

連結:http://www.cnblogs.com/javincoder/archive/2010/08/09/1795463.html

本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/archive/2010/12/27/1917874.html,如需轉載請自行聯系原作者