養成良好的編碼風格是極其必要的,誰也不愿意看到一堆雜亂無章的代碼,將來你或者別人在維護的時候是多么的痛苦,所以,從現在開始,養成良好的編碼習慣,包括變量命名,注釋,代碼縮進
....
。
1?.利用Pascal的方式定義類型、方法名和常量??
public?class?SomeClass? ?{ ? const?int?DefaultSize=100;? ? public?SomeMethod() ? { ? } }
|
?
2.
對于局部變量和方法的參數使用駱駝命名法
int?number; ?
void?MyMethod(int?someNumber) ?
{}
|
?
3.
接口的名稱前加上
I
interface?ImyInterface ??
{…}
|
?
4.
在私有成員變量前面加上
m_
。對于
m_
后面的變量名使用駱駝命名方法
public?class?SomeClass ??
{ ?
private?int?m_Number; ??
}
|
?
5.對自定義的屬性類加上后綴Attribute
?
6.對自定義的異常類加上后綴Exception
?
7.方法的命名使用動詞----對象對,例如ShowDialog()
?
8.有返回值的方法的命名中要有返回值的描述,例如GetObjectState()
?
9.
使用帶有說明性的變量名
a)?避免單字符的變量名,例如I或t等。使用類似于index或temp這樣有意義的名字。
b)?對于public或protected類型的變量避免使用匈牙利表示法。
c)?
不要縮寫單詞(例如用
num
取代
number
)。
?
10
.總是使用
C#
預定義而不要使用
System
名稱空間中的別名,例如:
使用object而不是Object
使用string而不是String
使用int而不是int32
?
11.
在使用泛型的時候,類型的首字母要大寫。當處理
.NET
中的
Type
類型的時候,保留
Type
后綴。
(C#2.0
新特性
)
//正確??
public?class?LinkedList<K,T> ??
{…} ??
?
//避免??
public?class?LinkedList<KeyType,DataType> ??
{….}
|
?
12.
使用有意義的名字定義名稱空間,例如產品名或者公司名
?
13.
避免通過全限定方式使用類型名稱,使用
using
關鍵字。
?
14.
避免在一個名稱空間中使用
using
關鍵字
?
15.
把所有系統框架提供的名稱空間組織到一起,把第三方提供的名稱空間放到系統名稱空間的下面
using?System; ??
using?System.Collection.Generic; ??
using?System.ComponentModel; ??
using?System.Data; ?
using?MyCompany; ?
using?MyControls;
|
?
16.
使用代理推導而不要顯式的實例化一個化代理(
C#2.0
新特性)
delegate?void?SomeDelegate(); ??
public?void?SomeMethod() ??
{…} ??
SomeDelegate?someDelegate=SomeMethod;
|
?
17.
維護嚴格的代碼縮進。不要使用
tabs
或非標準的縮進,例如一個空格。推薦的縮進是
3
到
4
個空格。
?
18.
在和你的代碼縮進處于同一個級別處為該行代碼添加注釋。
?
19.
所有的注釋都應該通過拼寫檢查。注釋中的錯誤拼寫意味著開發進度的延緩。
?
20.
所有的類成員變量應該被聲明在類的頂部,并用一個空行把它們和方法以及屬性的聲明區分開
public?class?MyClass ??
{ ??? ??
int?m_Number; ??
string?m_Name; ??
public?void?SomeMethod1(); ??
public?void?SomeMethod2(); ??
}
|
?
21.
在最靠近一個局部變量被使用的地方聲明該局部變量。
?
22.
一個文件名應該能夠反映它所對應的類名
?
23.
當使用一個部分類并把該類分布到不同的文件中時,在每一個文件名末尾都加上該文件實現的部分在類整體中扮演的作用。
例如:
//?In?MyClass.cs ??
public?partial?class?MyClass ??
{…} ??
//In?MyClass.Designer.cs ??
public?partial?class?MyClass ??
{…}
|
?
24.
總是要把花括號“
{”
放在新的一行
?
編碼實踐
:
1.?
避免在同一個文件中放置多個類
2.?
一個文件應該只向在一個名稱空間內定義類型。避免在一個文件中使用多個名稱空間
3.?
避免在一個文件內寫多于
500
行的代碼(機器自動生成的代碼除外)
4.?
避免寫超過
25
行代碼的方法
5.?
避免寫超過
5
個參數的方法。如果要傳遞多個參數,使用結構。
6.?
一行不要超過
80
個字符
7.?
不要手動去修改任何機器生成的代碼
a)?
如果修改了機器生成的代碼,修改你的編碼方式來適應這個編碼標準
b)?
盡可能使用
partial?classes
特性,以提高可維護性。
(C#2.0
新特性
)
8.?
避免對那些很直觀的內容作注釋。代碼本身應該能夠解釋其本身的含義。由可讀的變量名和方法名構成的優質代碼應該不需要注釋。
9.?
注釋應該只說明操作的一些前提假設、算法的內部信息等內容。
10.?
避免對方法進行注釋
a)?
使用充足的外部文檔對
API
進行說明
b)?
只有對那些其他開發者的提示信息才有必要放到方法級的注釋中來
11.?
除了
0
和
1
,絕對不要對數值進行硬編碼,通過聲明一個常量來代替該數值
12.?
只對那些亙古不變的數值使用
const
關鍵字,例如一周的天數。
13.?避免對只讀(read-only)的變量使用const關鍵字。在這種情況下,直接使用readonly關鍵字
public?class?MyClass ??
{ ??
public?const?int?DaysInWeek=7; ??
pubic?readonly?int?Number; ??
public?MyClass(int?someValue) ??
{ ??
Number=someValue; ??
} ??
}
|
14.?對每一個假設進行斷言。平均起來,每5行應有一個斷言。
using?System.Diagnostics; ??
object?GetObject() ??
{…} ??
object?someObject=GetObject(); ??
Debug.assert(someObject!=null);
|
15.?
每一行代碼都應該以白盒測試的方式進行審讀。
16.?
只捕捉那些你自己能夠顯式處理的異常。
17.?
如果在
catch
語句塊中需要拋出異常,則只拋出該
catch
所捕捉到的異常(或基于該異常而創建的其他異常),這樣可以維護原始錯誤所在的堆棧位置。
catch(Exception?exception) ??
{ ??
MessageBox.Show(exception.Message); ??
throw;//或throw?exception; ??
}
|
18.?
避免利用返回值作為函數的錯誤代碼。
19.?
避免自定義異常類。
20.?
當自定義異常類的時候:
a)?讓你自定義的異常類從Exception類繼承
b)?
提供自定義的串行化機制
21.?避免在一個程序集中(assembly)中定義多個Main()方法。
22.?只把那些絕對需要的方法定義成public,而其它的方法定義成internal。
23.?避免friend?assemblies,因為這會增加程序集之間的耦合性。
24.?
避免讓你的代碼依賴于運行在某個特定地方的程序集。
25.?在application?assembly(EXE?client?assemblies)中最小化代碼量。使用類庫來包含業務邏輯。
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
語句,總使用一對
{}
把下面的語句塊包含起來,哪怕只有一條語句也是如此。
29.?
避免使用三元條件操作符。
30.?
避免利用函數返回的
Boolean
值作為條件語句。把返回值賦給一個局部變量,然后再檢測。
Bool?IsEverythingOK() ??
{…} ??
?
//避免??
if(IsEverythingOk()) ??
{…} ??
?
//正確??
bool?ok=IsEverythingOK(); ??
if?(ok) ??
{…}
|
31.?
總是使用以零為基數的數組。
32.?
總是使用一個
for
循環顯式的初始化一個引用成員的數組:
public?class?MyClass
{}
const?int?ArraySize=100; ??
MyClass[]?array=new?MyClass[ArraySize]; ??
For?(int?index=0;index<array.Length;index++) ??
{
array[index]=new?MyClass(); ??
}
|
33.?使用屬性來替代public或protected類型的成員變量。
34.?不要使用繼承下來的new操作符,使用override關鍵字覆寫new的實現。
35.?在一個非密封(non-sealed)類中,總是把那些public和protected的方法定義成virtual。
36.?除非為了和其它語言進行互動,否則絕不要使用不安(unsafe)的代碼。
37.?
避免顯示類型轉換。使用
as
關鍵字安全的轉換到另一個類型。
Dog?dog=new?GermanShepherd(); ??
GermanShepherd?shepherd=dog?as?GermanShepherd; ?
if?(shepherd!=null) ??
{…}
|
38.?
在調用一個代理前,總是檢查它是否為
null
。
39.?不要提供public的事件成員變量。改用Event?Accessor。
Public?class?MyPublisher ??
{ ??
MyDelegate?m_SomeEvent; ??
Public?event?MyDelegate?SomeEvent ??
{ ??
add ??
{ ??
m_SomeEvent+=value; ??
} ??
remove ??
{ ??
m_SomeEvent-=value; ??
} ??
} ??
}
|
40.?
避免定義事件處理代理。
使用EventHandler<T>或者GenericEventHandler。
41.?
避免顯示觸發事件。使用
EventsHelper
安全的發布事件。
42.?
總是使用接口。
43.?
接口和類中方法和屬性的比應該在
2:1
左右。
44.?
避免只有一個成員的接口。
45.?
努力保證一個接口有
3~5
個成員。
46.?
不要讓一個接口中成員的數量超過
20
,而
12
則是更為實際的限制。
47.?避免在接口中包含事件。
48.?
當使用抽象類的時候,提供一個接口。
49.?
在類繼承結構中暴露接口。
50.?
推薦使用顯式接口實現。
51.?
從來不要假設一個類型支持某個接口。在使用前總是要詢問一下。
SomeType?obj1; ??
ImyInterface?obj2; ??? ??
/*Some?code?to?initialize?obj1,then:*/ ??
obj2=obj1?as?ImyInterface; ??
if(obj2!=null) ??
{ ??
obj2.Method1(); ?
} ?
else ?
{ ?
//Handle?erro?in?expected?interface ??
}
|
52.?
不要硬編碼向用戶顯示的字符串。要使用資源。
53.?
不要硬編碼那些可能會隨發布環境變化而變化的字符串,例如數據庫連接字符串。
54.?使用String.Empty取代””
//避免??
string?name=””; ??
//正確??
string?name=String.Empty;
|
55.?使用一個長字符串的時候,使用StringBuilder代替string。
56.?避免在結構中提供方法
a)?參數化的構造函數是鼓勵使用的
b)?
可以重載運行符
57.?
當聲明了表態成員的時候,總是要提供一個表態構造函數。
58.?當早綁定(early-binding)可能的時候就盡量不要使用遲綁定(late-binding)。
59.?讓你的應用程序支持跟蹤和日志。
60.?
除了要在
switch
語句塊中實現代碼跳轉,不要使用
goto
關鍵字。
61.?總在switch語句的default情形提供一個斷言。
int?number=SomeMethod(); ??
swith(number) ??
{ ??
case?1:
???trace.WriteLine(“Case?1:”) ??
break; ??
case?2: ??
trace.Writeline(“Case?2:”);
break;??
default: ??
debug.Assert(false); ??
break; ??
}
|
62.?
除了在一個構造函數中調用其它的構造函數之外,不要使用
this
關鍵字。
//Example?of?proper?use?of?‘this’ ??
public?class?MyClass ??
{ ??
public?MyClass(string?message) ??
{ ??} ??
public?MyClass():this(“Hello”) ??
{ ??}
}
|
63.?
不要使用
base
關鍵字訪問基類的成員,除非你在調用一個基類構造函數的時候要決議一個子類的名稱沖突
//Example?of?proper?use?of?‘base’ ??
public?class?Dog ??
{ ??
public?Dog(string?name) ??
{ ?} ??
virtual?public?void?Bark(int?howlong) ??
{ ??} ??
}?
public?class?GermanShepherd:Dog ??
{ ??
?public?GermanShepherd(string?name):base(name) ??
{ ??} ??
override?public?void?Bark(int?howLong) ??
{ ??
base.Bark(howLong) ??
} ??
}
|
64.?不要使用GC.AddMemoryPressure()
65.?不要依賴HandleCollector
66.?基于《Programming?.NET?components》2/e中第四章的內容實現Disponse()和Finalize()方法。
67.?總是在unchecked狀態下運行代碼(出于性能的原因),但是為了防止溢出或下溢操作,要果斷地使用checked模式。
Int?CalcPower(int?number,int?power) ??
{ ??
int?result=1; ??
for?(int?count=1;count<=power;count++) ??
{ ??
checked ??
{ ??
result*=number; ??
} ??
} ??
return?result; ??
}
|
68.?使用條件方法來取代顯式進行方法調用排除的代碼(#if…#endif)
public?class?MyClass
{ ??
[Conditional(“MySpecialCondition”)] ??
public?void?MyMethod() ??
{} ??
}
|
69.?
不要在泛型接口中定義約束。接口級的約束通常可以利用強類型來替代。
Public?class?Customer ??
{} ??
//避免: ??
public?interface?Ilist<T>?where?T:Customer ??
{} ??
?
//正確: ??
public?interface?IcustomerList:Ilist<Customer>
|
70.?
不要在接口上定義方法相關的約束。
71.?
不要在代理上定義約束。
72.?
如果一個類或方法提供了泛型和非泛型版本,那么優先選擇泛型版本