一、引言html
本文是一套面向C# programmer和C# developer進行開發所應遵循的開發規範程序員
按照此規範來開發C#程序可帶來如下益處:編程
代碼的編寫保持一致性,提升代碼的可讀性和可維護性,在團隊開發一個項目的狀況下,程序員之間可代碼共享,易於代碼的回顧框架
本規範是第一版,只適用於通常狀況的通用規範,並不能覆蓋全部的狀況編輯器
二、文件組織ide
2.1C#源文件佈局
類名或文件名要簡短,不要超過2000LOC,將代碼分割開,使結構清晰。將每一個類放在一個單獨的文件中,使用類名來命名文件名(固然擴展名是.cs),這種約定會使你們工做更簡單ui
2.2目錄設計this
爲每個命名空間建立一個目錄。(用MyProject/TestSuite/TestTier做爲MyProject.TestSuite.TestTier的路徑,而不用帶點的命名空間名作路徑)這樣能夠更容易地將命名空間映射到目錄編碼
層次劃分。
三、縮進
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.1塊註釋
塊註釋一般應該是被避免的 。推薦使用///註釋做爲C#的標準聲明。若是但願用塊註釋時你應該用如下風格:
/*Line1
*Line2
*Line3
*/
由於這樣能夠爲讀者將註釋塊與代碼塊區分開。雖然並不提倡使用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
///</exception>
爲了被認做是XML註釋行,全部的行都必須用三個反斜線開始。標籤有如下兩類:
文件說明項 格式/參考
第一類包括像<summary><param>or<exception> 的標籤。描述一個程序的API元素的這些文檔說明項必須寫清楚以方便其餘程序員。如上面的多行註釋示例所示,這些標籤一般帶有名
稱或cref屬性。編譯器會檢查這些屬性,因此它們必須是有效正確的。第二類用諸如<code>,<list>or<para>標籤,用於控制備註說明的佈局。文件能夠用‘文件’菜單中的「建立」菜單產生。文件
以html格式產生:
五、聲明
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例如對全局計數的更智能命名等等)—
· 使用Camel狀況(參考8.1.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 |
Pascal Casing |
Starts with I |
Enum values |
Pascal Casing |
|
Enum type |
Pascal Casing |
|
Events |
Pascal Casing |
|
Exception class |
Pascal Casing |
End with Exception |
public Fields |
Pascal Casing |
|
Methods |
Pascal Casing |
|
Namespace |
Pascal Casing |
|
Property |
Pascal Casing |
|
Protected/private Fields |
Camel Casing |
|
Parameters |
Camel Casing |
|
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 萬一像這樣,使得從新考慮這個原則更有意義。通常來講,當同一個計數器或索引器被重用,給它們有意義的名字。