[點晴永久免費OA]C#編程規(guī)范你做到了幾點?。?/h3>
|
admin
2020年3月3日 1:46 本文熱度 2636 |
1. 避免將多個類放在一個文件里面。
2. 一個文件應(yīng)該只有一個命名空間,避免將多個命名空間放在同一個文件里面。
3. 一個文件最好不要超過500行的代碼(不包括IDE產(chǎn)生的代碼)。
4. 一個方法的代碼長度最好不要超過25行。
5. 避免方法中有超過5個參數(shù)的情況。如果超過了,則應(yīng)使用 struct 來傳遞多個參數(shù)。
6. 每行代碼不要超過80個字符。
7. 原則上,盡量不要手工的修改機器產(chǎn)生的代碼。
a) 如果需要編輯機器(IDE)產(chǎn)生的代碼,編輯格式和風(fēng)格要符合該編碼標準。
b) 盡可能地使用片斷類來把被保持的部分分解為各個因素
注:這里的翻譯參考了靈感之源老兄的說法,在Visual c#2005中,C#的語法已經(jīng)支持partial修飾符,它的作用是可以將一個完整的類分解各個部分類,在編譯時,編譯器會將它們構(gòu)造為一個類。
8. 避免利用注釋解釋顯而易見的代碼。
a) 代碼應(yīng)該可以自解釋。好的代碼本身就應(yīng)具體良好的可讀性,所使用的變量和方法命名一般情況下不需要注釋。
9. 文檔應(yīng)該僅用于assumptions, algorithm insights等等.
10. 避免使用方法級的文檔。
a) 使用擴展的API文檔進行說明。
b) 只有在該方法需要被其他的開發(fā)者使用的時候才使用方法級的注釋。(在C#中就是///)
11. 不要硬編碼數(shù)字的值,總是使用構(gòu)造函數(shù)設(shè)定其值。
12. 只有是自然結(jié)構(gòu)才能直接使用const(常量),比如一個星期的天數(shù)。
13. 區(qū)別只讀變量及常量的使用方法,如果想實現(xiàn)只讀變量,可以直接使用readonly 修飾符。
public class MyClass
{
public readonly int Number;
public MyClass(int someValue)
{
Number = someValue;
}
public const int DaysInWeek = 7;
}
14. 每個假設(shè)必須使用Assert檢查
a) 平均每15行要有一次檢查(Assert)
using System.Diagnostics;
object GetObject()
{…}
object obj = GetObject();
Debug.Assert(obj != null);
15. 代碼的每一行都應(yīng)該通過白盒方式的測試。
16. 只拋出已經(jīng)顯示處理的異常。
17. 在捕獲(catch)語句的拋出異常子句中(throw),總是拋出原始異常,用以維護原始錯誤的堆棧分配。 catch(Exception exception)
{
MessageBox.Show(exception.Message);
throw ; //和throw exception一樣。
}
注:同理,不推薦在循環(huán)語句中,進行直接的return操作。 for (int i=0;i<100;i++) { if (i==10) { return; //不推薦的方式 } } 18. 避免方法的返回值是錯誤代碼。
19. 盡量避免定義自定義異常類。
20. 當(dāng)需要定義自定義的異常時:
a) 自定義異常要繼承于ApplicationException。
b) 提供自定義的序列化功能。
21. 避免在單個程序集里使用多個Main方法。
22. 只對外公布必要的操作,其他的則為internal。
23. 避免使用友元程序集,因為它會增加程序集間的耦合度。
24. 避免編寫從指定的位置加載的程序集的代碼。
25. 使應(yīng)用程序集盡量為最小化代碼(EXE客戶程序)。使用類庫來替換包含的商務(wù)邏輯。
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語句的內(nèi)容用大括號擴起來。
29. 避免使用trinary條件操作符。
30. 避免在條件語句中調(diào)用返回bool值的函數(shù)。可以使用局部變量并檢查這些局部變量。
bool IsEverythingOK()
{…}
//避免
if (IsEverythingOK ())
{…}
//替換方案
bool ok = IsEverythingOK();
if (ok)
{…}
31. 總是使用基于0開始的數(shù)組。
32. 在循環(huán)中總是顯式的初始化引用類型的數(shù)組。
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. 避免顯式的轉(zhuǎn)換,使用as操作符進行兼容類型的轉(zhuǎn)換。
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog as GermanShepherd;
if (shepherd != null )
{…}
38. 當(dāng)類成員包括委托的時候
a) 在調(diào)用委托前,將它拷貝到一個本地變量中,用以避免并發(fā)爭用條件。
b) 在調(diào)用委托之前一定要檢查它是否為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. 接口中的成員不應(yīng)該超過20個。
a) 根據(jù)實際情況可能限制為12個
46. 避免接口成員中包含事件。
47. 避免使用抽象方法而使用接口替換。
48. 在類層次中顯示接口。
49. 推薦使用顯式的接口實現(xiàn)。
50. 從不假設(shè)一個類型兼容一個接口,并應(yīng)防止查詢那些接口。
SomeType obj1;
IMyInterface obj2;
/* 假設(shè)已有代碼初始化過obj1,接下來 */
obj2 = obj1 as IMyInterface;
if (obj2 != null)
{
obj2.Method1();
}
else
{
//處理錯誤
}
51. 表現(xiàn)給最終用戶的字符串(一般指UI界面中的部分)不要使用直接編碼,而應(yīng)該要使用資源文件來替換。
注:這樣做的目的是方便軟件的本地化。
52. 不要直接編寫可能會更改的基于配置的字符串,比如連接字符串。
53. 當(dāng)需要構(gòu)建較長的字符串的時候,應(yīng)該考慮使用StringBuilder不要使用string來處理。
注:string每次要創(chuàng)建一個新的實例,較占用空間,并產(chǎn)生了相對StringBuilder更大的性能消耗。對于過于頻繁的字符串操作,采用StringBuilder是一個良好的習(xí)慣。
54. 避免在結(jié)構(gòu)里面提供方法。
a) 建議使用參數(shù)化構(gòu)造函數(shù)
b) 可以重載操作符
55. 總是要給靜態(tài)變量提供靜態(tài)構(gòu)造函數(shù)。
56. 在能夠使用早期綁定的情況下,盡量避免使用后期綁定。
注:后期綁定雖然靈活,但帶來的不僅僅是性能上的消耗,更多的是編碼上的復(fù)雜性和混亂的邏輯。
57. 使用應(yīng)用程序的日志和跟蹤。
58. 除非在不完全的switch語句中否則不要使用goto語句。
注:原則上不應(yīng)使用goto語句,除非在能夠大大減輕編碼的復(fù)雜性,并不影響可讀性的前提下才允許使用。
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. 除非在構(gòu)造函數(shù)中調(diào)用其他構(gòu)造函數(shù)否則不要使用this指針。
// 正確使用this的例子
public class MyClass
{
public MyClass(string message )
{}
public MyClass() : this("hello")
{}
}
61. 除非你想重寫子類中存在名稱沖突的成員或者調(diào)用基類的構(gòu)造函數(shù)否則不要使用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. 基于模板的時候要實現(xiàn)Dispose()和Finalize()兩個方法。
63. 通常情況下避免有從System.Object轉(zhuǎn)換來和由System.Object轉(zhuǎn)換去的代碼,而使用強制轉(zhuǎn)換或者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. 在一般情況下不要定義有限制符的接口。接口的限制級別通??梢杂脧婎愋蛠硖鎿Q之。
public class Customer
{…}
//避免:
public interface IList<T> where T : Customer
{…}
//正確:
public interface ICustomerList : IList<Customer>
{…}
65. 不確定在接口內(nèi)的具體方法的限制條件。
66. 總是選擇使用C#內(nèi)置(一般的generics)的數(shù)據(jù)結(jié)構(gòu) 67、初始化類的實例時,除非十分必要,否則不要賦null值。 68、使用后的實例,盡量不要將該實例的引用賦值和為nul,尤其是采用public來修飾的類成員l。 1) 如果該實例是臨時引用,請使用using語句,然后在程序塊中使用。 2) 如果需要釋放資源,應(yīng)可能地使用Dispose,采用null值的方法,該引用在指向下一個實例前,不會被回收。
規(guī)范是要看下的,但沒必要完全照做。
重要的是要清楚各條規(guī)范設(shè)立的目的是什么,適應(yīng)什么場合。
之所以會成為規(guī)范,是因為有很多人都用,至少說明了規(guī)范有其優(yōu)點存在。但凡事都不是絕對的,在不同的應(yīng)用場合及客觀條件下,“優(yōu)點”有時也會成為絆腳石。所以怎么應(yīng)用規(guī)范要視具體情況而定。在下相信你的上司能夠在
1、可讀性好的代碼
2、可讀性很差但效率要高出數(shù)倍的代碼
上面兩者中做出明智的選擇的。