看我72條——C#編碼標(biāo)準(zhǔn)
C#編碼標(biāo)準(zhǔn)(上)
1.避免在同一個(gè)文件中放置多個(gè)類
2.一個(gè)文件應(yīng)該只在一個(gè)名稱空間內(nèi)定義類型,避免在一個(gè)文件中使用多個(gè)名稱空間
3.避免在一個(gè)文件內(nèi)寫多于500行的代碼(機(jī)器自動(dòng)生成的代碼除外)
4.避免寫超過25號(hào)代碼的方法
5.避免寫超過5個(gè)參數(shù)的方法。如果要傳遞多個(gè)參數(shù),使用結(jié)構(gòu)。
6.一行不要超過80個(gè)字符
7.不要手動(dòng)去修改任何機(jī)器生成的代碼
a)如果修改了機(jī)器生成的代碼,修改你的編碼方式來使用這個(gè)編碼標(biāo)準(zhǔn)
b)盡可能使用partial classes特征,以提高可維護(hù)性(C#2.0新特性)
8.避免對(duì)那些很直觀的內(nèi)容作注釋。代碼本身應(yīng)該能夠解釋其自身的含義。由可讀的變量名和方法名構(gòu)成的優(yōu)質(zhì)代碼應(yīng)該不需要注釋。
9.注釋應(yīng)該只說明操作的一些前提假設(shè)、算法的內(nèi)部信息等內(nèi)容
10.避免對(duì)方法進(jìn)行注釋
a)使用充足的外部文檔對(duì)API進(jìn)行說明
b)只有對(duì)那些其他開發(fā)者的提示信息才有必要放到方法級(jí)的注釋中來
11.除了0和1,絕對(duì)不要對(duì)數(shù)值進(jìn)行硬編碼,通過聲明一個(gè)常量來代替該數(shù)值
12.只對(duì)那些亙古不變的數(shù)值使用const關(guān)鍵字,例如一周的天數(shù)
13.避免對(duì)只讀(read-only)的變量使用const關(guān)鍵字。在這種情況下,直接使用readonly關(guān)鍵字
- public class MyClass
- {
- public const int DaysInWeek = 7;
- public readonly int Number;
- public MyClass(int someValue)
- {
- Number = someValue;
- }
- }
14.對(duì)每一個(gè)假設(shè)進(jìn)行斷言。平均起來,每5行應(yīng)有一個(gè)斷言
- using System.Diagnostics;
- object GetObject()
- {…}
- object someObject = GetObject();
- Debug.Assert(someObject != null);
15.每一行代碼都應(yīng)該以白盒測(cè)試的方式進(jìn)行審讀
16.只捕捉那些你自己能夠顯式處理的異常
17.如果在catch語句塊中需要拋出異常,則只拋出該catch所捕捉到異常(或基于該異常而創(chuàng)建的其它異常),這樣可以維護(hù)原始錯(cuò)誤所在的堆棧位置;
- catch(Exception exception)
- {
- MessageBox.Show(exception.Mesage);
- throw; //或throw,exception;
- }
18.避免利用返回值作為函數(shù)的錯(cuò)誤代碼
19.避免自定義異常類
20.當(dāng)自定義異常類的時(shí)候
a)讓你自定義的異常類從Execption類繼承
b)提供自定義的串行化機(jī)制
21.避免在一個(gè)程序集(assembly)中定義多個(gè)Main()方法
22.只把那些絕對(duì)需要的方法定義成public,而其它的方法定義成internal
23.避免friend assemblies,因?yàn)檫@會(huì)增加程序集之間的偶合性
24.避免讓你的代碼依賴于運(yùn)行在某個(gè)特定地方的程序集
C#編碼標(biāo)準(zhǔn)(中)
25.在application assembly (EXE client assemblies)中最小化代碼量,使用類庫來包含業(yè)務(wù)邏輯
26.避免顯示指定枚舉的值
- //正確
- public enum Color
- {
- Red, Green, Blue
- }
- //避免
- public enum Color
- {
- Red = 1, Green = 2, Blue = 3
- }
27.避免為枚舉指定一個(gè)類型
- //避免
- public enum Color:long
- {
- Red, Grenn, Blue
- }
28.對(duì)于if語句,總使用一對(duì){}把下面的語句塊包含起來,哪怕只有一條語句也是如此
29.避免使用三元條件操作符
30.避免利用函數(shù)返回的Boolean值作為條件語句。把返回值賦給一個(gè)局部變量,然后再檢測(cè)
- bool IsEverythingOK()
- {…}
- //避免
- if (IsEverythingOK) {…}
- //正確
- bool ok = IsEverythingOK()
- if (ok) {…}
31.總是使用以零為基數(shù)的數(shù)組
32.總是使用一個(gè)for循環(huán)顯式的初始化一個(gè)引用成員的數(shù)組
- 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關(guān)鍵字覆寫new的實(shí)現(xiàn)
35.在一個(gè)非密封(non-sealed)類中,總是把那些public和protected的方法定義成virtual
36.除非為了和其他語言進(jìn)行互動(dòng),否則絕不要使用不安全(unsafe)的代碼
37.避免顯示類型轉(zhuǎn)換。使用as關(guān)鍵字安全的轉(zhuǎn)換到另一個(gè)類型
- Dog dog = new GermanShepherd();
- GermanShepherd shepherd = dog as GermanShepherd;
- if (shepherd != null) {…}
38.在調(diào)用一個(gè)代理前,總是檢查它是否為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或者GenericEventHandler。其中GenericEventHandler定義在《Programming .NET components》2/e第6章
41.避免顯示出發(fā)事件。使用EventsHelper安全的發(fā)布事件。EnentHelper定義在《Programming .NET components》2/e第6~8章中
42.總是使用接口
43.接口和類中方法和屬性的比應(yīng)該在2:1左右
44.避免只有一個(gè)成員的接口
45.努力保證一個(gè)接口有3-5個(gè)成員
46.不要讓一個(gè)接口中成員的數(shù)量超過20個(gè),而12則是更實(shí)際的限制
47.避免在接口中包含事件
48.當(dāng)使用抽象類的時(shí)候,提供一個(gè)接口
C#編碼標(biāo)準(zhǔn)(下)
49.在類繼承結(jié)構(gòu)中暴露接口
50。推薦使用顯式接口實(shí)現(xiàn)
51.從來不要假設(shè)一個(gè)類型支持某個(gè)接口。在使用前總是要詢問一下
- SomeType obj1;
- IMyInterface obj2
- /* Some code to initialize obj1, then; */
- obj2 = obj1 as IMyInterface;
- if (obj2 != null)
- {
- obj2.Method1();
- }
- else
- {
- //Handle error in expected interface
- }
52.不要硬編碼向用戶顯示字符串。要使用資源
53.不要硬編碼那些可能會(huì)隨發(fā)布環(huán)境變化而變化的字符串,例如數(shù)據(jù)庫連接字符串
54.使用String.Empty取代“”
- //避免
- tring name = “”;
- //正確
- tring name = String.Empty;
55.用一個(gè)長(zhǎng)字符串的時(shí)候,使用StringBuiler代替string
56.避免在結(jié)構(gòu)中提供方法
a)參數(shù)化的構(gòu)造函數(shù)是鼓勵(lì)使用的
b)可以重載運(yùn)算符
57.當(dāng)聲明了靜態(tài)成員的時(shí)候,總是要提供一個(gè)靜態(tài)構(gòu)造函數(shù)
58.當(dāng)早綁定(early-binding)可能的時(shí)候就盡量不要使用遲綁定(late-binding)
59.讓你的應(yīng)用程序支持跟蹤和調(diào)試
60.除了要在switch語句塊中實(shí)現(xiàn)代碼跳轉(zhuǎn),不要使用goto關(guān)鍵字
61.總在switch語句的default情形提供一個(gè)斷言
- int number = SomeMethod();
- switch (number)
- {
- case 1:
- Trace.WriteLine(“Case 1:”);
- break;
- Case 2:
- Trace.WriteLine(“Case 2:”);
- break;
- default:
- Debug.Assert(false);
- break;
- }
62.除了在一個(gè)構(gòu)造函數(shù)中調(diào)用其它的構(gòu)造函數(shù)之外,不要使用this關(guān)鍵字
- //Example of proper use of ‘this’
- public class MyClass
- {
- public MyClass(string message) {…}
- public MyClass(): this(“Hello”) {…}
- }
63.不要使用base關(guān)鍵字訪問基類的成員,除非你在調(diào)用一個(gè)函數(shù)的時(shí)候要決議一個(gè)子類的名稱沖突
- //Example of proper use of ‘base’
- public class Dog
- {
- public Dog(stinrg name) {…}
- virtual public void Bark(int howLong) {…}
- }
- public class GermanShepherd:Dog
- {
- public GermanShepherd(string name):base(name) {…}
- override public void Brak(int howLong)
- {
- base.Brak(howlong);
- }
- }
64.不要使用GC.AddMemoryPressure()
65.不要依賴HandleCollector
66.基于《Programming .NET components》2/e中第4章內(nèi)容實(shí)現(xiàn)Dispose()和Finalize()方法
67.總是在unchecked狀態(tài)下運(yùn)行代碼(出于性能的原因),但是為了防止溢出或下溢操作,要果斷地使用checked模式
- int CalcPower(int number, int power)
- {
- int result = 1;
- for (int count = 1; count < = power; count++)
- {
- checked
- {
- result *= number;
- }
- }
- return result;
- }
68.使用條件方法來取代顯式進(jìn)行方法調(diào)用排除的代碼(#if…#endif)
- public class MyClass
- {
- [Conditional(“MySpecialCondition”)]
- public void MyMethod() {…}
- }
69.不要在泛型接口中定義約束。接口級(jí)的約束通??梢岳脧?qiáng)類型來替代
- public class Customer {…}
- //避免
- public interface IList where T:Customer {…}
- //正確
- public interface ICustomerList:IList {…}
70.不要在接口上定義方法相關(guān)的約束
71.不要再代理上定義約束
72.如果一個(gè)類或方法提供了泛型和非泛型版本,那么優(yōu)先選擇泛型版本
【編輯推薦】