陳年的文檔,不過很不錯整理出來發(fā)到博客上,還有更多的朋友需要。
目 錄
10.3. 構(gòu)造函數(shù)的設(shè)計規(guī)范 20
10.5. 參數(shù)的設(shè)計規(guī)范 21
10.5.1. 參數(shù)設(shè)計中枚舉和布爾參數(shù)的選擇規(guī)范 21
10.5.2. 參數(shù)驗(yàn)證的規(guī)范: 22
12.3. 標(biāo)準(zhǔn)異常類的使用: 23
12.3.1. Exception與SystemException 23
12.3.2. InvalidOperationException 24
12.3.3. ArgumentException,ArgumentNullException,ArgumentOutOfRangeException 24
12.3.4. NullRefernceException,IndexOutOfRangeException,AccessViolationException 24
12.3.5. StackOverflowException: 24
12.3.6. OutOfMemoryException: 24
12.4. 自定義異常類型設(shè)計規(guī)則: 24
本規(guī)范為一套編寫高效可靠的 C# 代碼的標(biāo)準(zhǔn)、約定和指南。它以安全可靠的軟件工程原則為基礎(chǔ),使代碼易于理解、維護(hù)和增強(qiáng),提高生產(chǎn)效率。同時,將帶來更大的一致性,使軟件開發(fā)團(tuán)隊(duì)的效率明顯提高。
本規(guī)范適用于公司所有的C#源代碼,為詳細(xì)設(shè)計,代碼編寫和代碼審核提供參考和依據(jù)。
本規(guī)范中的建議分為四種:要,建議,避免,不要,表示需要遵循的級別。文檔中會以粗體表示。對于應(yīng)遵循的規(guī)范,前面會以“?”來表示,對不好的做法前面會以“′”來表示:
要:描述必須遵循的規(guī)范。例如:
異常類要以“Exception”做為后綴;
建議:描述在一般情況下應(yīng)該遵循的規(guī)范,但如果完全理解規(guī)范背后的道理,并有很好的理由不遵循它時,也不畏懼打破常規(guī)。例如:
強(qiáng)制類型轉(zhuǎn)換時,在類型和變量之間建議加一空格。
不要:描述一些幾乎絕對絕不應(yīng)該違反的規(guī)范。例如:
′ 每個函數(shù)有效代碼(不包括注釋和空行)長度不要超過50行。
避免:與建議相對,一般情況下應(yīng)該遵循,但有很好的理由時也可以打破。例如:
′ 避免塊內(nèi)部的變量與它外部的變量名相同。
對一些規(guī)范內(nèi)容一并提供了示例代碼。
要使一個Tab為4個空格長。
要使一個代碼塊內(nèi)的代碼都統(tǒng)一縮進(jìn)一個Tab長度。
建議適當(dāng)?shù)脑黾涌招?,來增加代碼的可讀性。
在在類,接口以及彼此之間要有兩行空行:
在下列情況之間要有一行空行:
方法之間;
局部變量和它后邊的語句之間;
方法內(nèi)的功能邏輯部分之間;
′ 每個函數(shù)有效代碼(不包括注釋和空行)長度不要超過50行。
開括號“{”要放在塊的所有者的下一行,單起一行;
閉括號“}”要單獨(dú)放在代碼塊的最后一行,單起一行。
′ 每行代碼和注釋不要超過70個字符或屏幕的寬度,如超過則應(yīng)換行,換行后的代碼應(yīng)該縮進(jìn)一個Tab。
′ 括號和它里面的字符之間不要出現(xiàn)空格。括號應(yīng)該和它前邊的關(guān)鍵詞留有空格,如:while (true) {};
′ 但是方法名和左括號之間不要有空格。
參數(shù)之間的逗號后要加一空格。如:method1(int i1, int i2)
for語句里的表達(dá)式之間要加一空格。如:for (expr1; expr2; expr3)
二元操作符和操作數(shù)之間要用空格隔開。如:i + c;
強(qiáng)制類型轉(zhuǎn)換時,在類型和變量之間要加一空格。如:(int) i ;
注釋應(yīng)該增加代碼的清晰度;
保持注釋的簡潔,不是任何代碼都需要注釋的,過多的注釋反而會影響代碼的可讀性。
′ 注釋不要包括其他的特殊字符。
建議先寫注釋,后寫代碼,注釋和代碼一起完成
如果語句塊(比如循環(huán)和條件分枝的代碼塊)代碼太長,嵌套太多,則在其結(jié)束“}”要加上注釋,標(biāo)志對應(yīng)的開始語句。如果分支條件邏輯比較復(fù)雜,也要加上注釋。
在VS2005環(huán)境中通過配置工程編譯時輸出XML文檔文件可以檢查注釋的完整情況,如果注釋不完整會報告編譯警告;
主要用來描述文件,類,方法,算法等,放在所描述對象的前邊。具體格式以IDE編輯器輸入“///”自動生成的格式為準(zhǔn),另外再附加我們自定義的格式,如下所列:
/// <Remark>作者,創(chuàng)建日期,修改日期</ Remark >
對類和接口的注釋必須加上上述標(biāo)記,對方法可以視情況考慮
主要用在方法內(nèi)部,對代碼,變量,流程等進(jìn)行說明。整個注釋占據(jù)一行。
與行注釋功能相似,放在代碼的同行,但是要與代碼之間有足夠的空間,便于分清。例:
int m = 4 ; // 注釋
如果一個程序塊內(nèi)有多個尾隨注釋,每個注釋的縮進(jìn)要保持一致。
項(xiàng)目 | 注釋哪些部分 |
參數(shù) | 參數(shù)用來做什么 任何約束或前提條件 |
字段/屬性 | 字段描述 |
類 | 類的目的 已知的問題 類的開發(fā)/維護(hù)歷史 |
接口 | 目的 它應(yīng)如何被使用以及如何不被使用 |
局部變量 | 用處/目的 |
成員函數(shù)注釋 | 成員函數(shù)做什么以及它為什么做這個 哪些參數(shù)必須傳遞給一個成員函數(shù) 成員函數(shù)返回什么 已知的問題 任何由某個成員函數(shù)拋出的異常 成員函數(shù)是如何改變對象的 包含任何修改代碼的歷史 如何在適當(dāng)情況下調(diào)用成員函數(shù)的例子適用的前提條件和后置條件 |
成員函數(shù)內(nèi)部注釋 | 控制結(jié)構(gòu) 代碼做了些什么以及為什么這樣做 局部變量 難或復(fù)雜的代碼 處理順序 |
新增代碼行的前后要有注釋行說明,對具體格式不作要求,但必須包含作者,新增時間,新增目的。在新增代碼的最后必須加上結(jié)束標(biāo)志;
刪除代碼行的前后要用注釋行說明,刪除代碼用注釋原有代碼的方法。注釋方法和內(nèi)容同新增;刪除的代碼行建議用#region XXX #endregion 代碼段折疊,保持代碼文件干凈整潔
修改代碼行建議以刪除代碼行后再新增代碼行的方式進(jìn)行(針對別人的代碼進(jìn)行修改時,必須標(biāo)明,對于自己的代碼進(jìn)行修改時,酌情進(jìn)行)。注釋方法和內(nèi)容同新增;
要使用可以準(zhǔn)確說明變量/字段/類的完整的英文描述符,如firstName。對一些作用顯而易見的變量可以采用簡單的命名,如在循環(huán)里的遞增(減)變量就可以被命名為 ” i ”。
要盡量采用項(xiàng)目所涉及領(lǐng)域的術(shù)語。
要采用大小寫混合,提高名字的可讀性。為區(qū)分一個標(biāo)識符中的多個單詞,把標(biāo)識符中的每個單詞的首字母大寫。不采用下劃線作分隔字符的寫法。有兩種適合的書寫方法,適應(yīng)于不同類型的標(biāo)識符:
PasalCasing:標(biāo)識符的第一個單詞的字母大寫;
camelCasing:標(biāo)識符的第一個單詞的字母小寫。
下表描述了不同類型標(biāo)識符的大小寫規(guī)則:
標(biāo)識符 | 大小寫 | 示例 |
命名空間 | Pascal | namespace Com.Techstar.ProductionCenter |
類型 | Pascal | public class DevsList |
接口 | Pascal | public interface ITableModel |
方法 | Pascal | public void UpdateData() |
屬性 | Pascal | Public int Length{…} |
事件 | Pascal | public event EventHandler Changed; |
私有字段 | Camel | private string fieldName; |
非私有字段 | Pascal | public string FieldName; |
枚舉值 | Pascal | FileMode{Append} |
參數(shù) | Camel | public void UpdateData(string fieldName) |
局部變量 | Camel | string fieldName; |
′ 避免使用縮寫,如果一定要使用,就謹(jǐn)慎使用。同時,應(yīng)該保留一個標(biāo)準(zhǔn)縮寫的列表,并且在使用時保持一致。
對常見縮略詞,兩個字母的縮寫要采用統(tǒng)一大小寫的方式(示例:ioStream,getIOStream);多字母縮寫采用首字母大寫,其他字母小寫的方式(示例:getHtmlTag);
′ 避免使用長名字(最好不超過 15 個字母)。
′ 避免使用相似或者僅在大小寫上有區(qū)別的名字。
公司域名(Techstar)+ 項(xiàng)目名稱 + 模塊名稱(可選),例如:
中心系統(tǒng)程序集:Techstar.ProductionCenter;
中心系統(tǒng)業(yè)務(wù)邏輯程序集:Techstar. ProductionCenter.Business;
采用和程序集命名相同的方式:公司域名(Techstar)+ 項(xiàng)目名稱 + 模塊名稱。 另外,一般情況下建議命名空間和目錄結(jié)構(gòu)相同。例如:
中心系統(tǒng):Techstar.ProductionCenter;
中心系統(tǒng)下的用戶控件:Techstar.ProductionCenter.UserControl;
中心系統(tǒng)業(yè)務(wù)邏輯:Techstar. ProductionCenter.Business;
中心系統(tǒng)數(shù)據(jù)訪問:Techstar. ProductionCenter.Data;
類的名字要用名詞;
′ 避免使用單詞的縮寫,除非它的縮寫已經(jīng)廣為人知,如HTTP。
接口的名字要以字母I開頭。保證對接口的標(biāo)準(zhǔn)實(shí)現(xiàn)名字只相差一個“I”前綴,例如對IComponent的標(biāo)準(zhǔn)實(shí)現(xiàn)為Component;
泛型類型參數(shù)的命名:命名要為T或者以T開頭的描述性名字,例如:
public class List<T>
public class MyClass<TSession>
′ 對同一項(xiàng)目的不同命名空間中的類,命名避免重復(fù)。避免引用時的沖突和混淆;
第一個單詞一般是動詞
如果方法返回一個成員變量的值,方法名一般為Get+成員變量名,如若返回的值 是bool變量,一般以Is作為前綴。另外,如果必要,考慮用屬性來替代方法,具 體建議見10.1.2節(jié);
如果方法修改一個成員變量的值,方法名一般為:Set + 成員變量名。同上,考慮 用屬性來替代方法;
按照使用范圍來分,我們代碼中的變量的基本上有以下幾種類型,類的公有變量;類的私有變量(受保護(hù)同公有);方法的參數(shù)變量;方法內(nèi)部使用的局部變量。這些變量的命名規(guī)則基本相同,見標(biāo)識符大小寫對照表。區(qū)別如下:
i. 類的公有變量按通常的方式命名,無特殊要求;
ii. 類的私有變量采用兩種方式均可:采用加“m”前綴,例如mWorkerName;
iii. 方法的參數(shù)變量采用camalString,例如workerName;
iv. 方法內(nèi)部的局部變量采用camalString,例如workerName;
′ 不要用_或&作為第一個字母;
盡量要使用短而且具有意義的單詞;
單字符的變量名一般只用于生命期非常短暫的變量。i,j,k,m,n一般用于integer;c,d,e 一般用于characters;s用于string
如果變量是集合,則變量名要用復(fù)數(shù)。例如表格的行數(shù),命名應(yīng)為:RowsCount;
命名組件要采用匈牙利命名法,所有前綴均應(yīng)遵循同一個組件名稱縮寫列表
縮寫的基本原則是取組件類名各單詞的第一個字母,如果只有一個單詞,則去掉其中的元音,留下輔音??s寫全部為小寫。
組件類型 | 縮寫 | 例子 |
Label | Lbl | lblNote |
TextBox | Txt | txtName |
Button | Btn | btnOK |
ImageButton | Ib | ibOK |
LinkButton | Lb | lbJump |
HyperLink | Hl | hlJump |
DropDownList | Ddl | ddlList |
CheckBox | Cb | cbChoice |
CheckBoxList | Cbl | cblGroup |
RadioButton | Rb | rbChoice |
RadioButtonList | Rbl | rblGroup |
Image | Img | imgBeauty |
Panel | Pnl | pnlTree |
TreeView | Tv | tvUnit |
WebComTable | Wct | wctBasic |
ImageDateTimeInput | Dti | dtiStart |
ComboBox | Cb | cbList |
MyImageButton | Mib | mibOK |
WebComm.TreeView | Tv | tvUnit |
PageBar | Pb | pbMaster |
每行要只有一個聲明,如果是聲明i,j,k之類的簡單變量可以放在一行;
除了for循環(huán)外,聲明要放在塊的最開始部分。for循環(huán)中的變量聲明可以放在for語句中。如:for(int i = 0; I < 10; i++) 。
′ 避免塊內(nèi)部的變量與它外部的變量名相同。
每行建議只有一條語句。
if-else,if-elseif語句,任何情況下,都應(yīng)該有“{”,“}”,格式如下:
if (condition)
{
statements;
}
else if (condition)
{
statements;
}
else
{
statements;
}
for語句格式如下:
for (initialization; condition; update)
{
statements;
}
如果語句為空:
for (initialization; condition; update) ;
while語句格式如下:
while (condition)
{
statements;
}
如果語句為空:
while (condition);
do-while語句格式如下:
do
{
statements;
}
while (condition);
switch語句,每個switch里都應(yīng)包含default子語句,格式如下:
switch (condition)
{
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
try-catch語句格式如下:
try
{
statements;
}
catch (ExceptionClass e)
{
statements;
}
finally
{
statements;
}
要確保每個類型由一組定義明確,相互關(guān)聯(lián)的成員組成,而不僅僅是一些無關(guān)功能的隨 機(jī)集合;
要用命名空間把類型組織成相關(guān)域的層次結(jié)構(gòu)。例如:
界面層:Techstar.ProductionCenter;
業(yè)務(wù)邏輯層:Techstar.ProductionCenter.Business;
數(shù)據(jù)訪問層:Techstar.ProductionCenter.Data;
′ 避免過深的命名空間;
′ 避免太多的命名空間;
要優(yōu)先采用類而不是接口。
接口的缺點(diǎn)在于語義變化時改變困難。注意接口并不是協(xié)定,把協(xié)定和實(shí)現(xiàn)分開并非一 定用接口實(shí)現(xiàn),用基類和抽象類同樣可以表達(dá);
建議使用抽象類而不是接口來解除協(xié)定與實(shí)現(xiàn)間的偶合;
要定義接口,來實(shí)現(xiàn)類似多重繼承的效果;
精心定義接口的標(biāo)志是一個接口只做一件事情。關(guān)鍵是接口的協(xié)定需要保持不變, 如果一個接口包含太多功能,那么這個胖接口產(chǎn)生變化的機(jī)會就會大得多。
′ 不要在抽象類中定義公有的或內(nèi)部受保護(hù)的構(gòu)造函數(shù)。因?yàn)槌橄箢悷o法實(shí)例化,所以這 種設(shè)計會誤導(dǎo)用戶;
要為抽象類定義受保護(hù)的構(gòu)造函數(shù)或內(nèi)部構(gòu)造函數(shù);
靜態(tài)類是一個只包含靜態(tài)成員的類,它提供了一種純面向?qū)ο笤O(shè)計和簡單性之間的一個權(quán)衡,廣泛用來提供類似于全局變量或一些通用功能。
要少用靜態(tài)類。靜態(tài)類應(yīng)該僅用作輔助類;
′ 避免把靜態(tài)類當(dāng)作雜物箱。每個靜態(tài)類都應(yīng)該有其明確目的;
不要在靜態(tài)類中聲明或覆蓋實(shí)例成員;
要用枚舉來加強(qiáng)那些表示值的集合的參數(shù),屬性以及返回值的類型性;
要優(yōu)先使用枚舉而不是靜態(tài)常量。例如:
//不好的寫法
public static class Color
{
public static int Red = 0;
public static int Green = 1;
public static int Blue = 2;
}
//好的寫法
public enum Color
{
Red,
Green,
Blue
}
′ 不要把枚舉用于開放的場合,例如操作系統(tǒng)的版本,朋友的名字等;
′ 枚舉最后一個值不要加逗號;
′ 枚舉中不要提供為了今后使用而保留的枚舉值;
方法,屬性,事件,構(gòu)造函數(shù)以及字段等統(tǒng)稱為成員。
′ 避免在重載中隨意的給參數(shù)命名。如果兩個重載中的某個參數(shù)表示相同的輸入,那么該參數(shù)的名字應(yīng)該相同。例如:
public class String
{
//好的寫法
public int IndexOf(string value) { ...}
public int IndexOf(string value, int startIndex) { ...}
//不好的寫法
public int IndexOf(string value) { ...}
public int IndexOf(string str, int startIndex) { ...}
}
′ 避免使重載成員的參數(shù)順序不一致。在所有的重載中,同名參數(shù)應(yīng)該出現(xiàn)在相同的位置。 例如:
public class EventLog
{
public EventLog();
public EventLog(string logName);
public EventLog(string logName, string machineName);
public EventLog(string logName, string machineName, string source);
}
較短的重載應(yīng)該僅僅調(diào)用較長的來實(shí)現(xiàn)。另外,重載如果需要擴(kuò)展性,把最長重載 做成虛函數(shù)。例如:
public class String
{
public int IndexOf(string s)
{
//調(diào)用
return IndexOf(s, 0);
}
public int IndexOf(string s, int startIndex)
{
//調(diào)用
return IndexOf(s, startIndex, s.Length);
}
public virtual int IndexOf(string s, int startIndex, int Count)
{
//實(shí)際的代碼
}
}
要允許可選參選為null。這樣做是為了避免調(diào)用者調(diào)用之前需要檢查參數(shù)是否null。例 如:
//允許為null時的調(diào)用
DrawGeometry(brush, pen, geometry);
//不允許為null時的調(diào)用
if (geometry == null) DrawGeometry(brush, pen);
else DrawGeometry(brush, pen, geometry);
基本原則是方法表示操作,屬性表示數(shù)據(jù)。如果其他各方面都一樣,優(yōu)先使用屬性而不 是方法。
要使用屬性,如果該成員表示類型的邏輯attribue
如果屬性的值存儲在內(nèi)存中,而提供屬性的目的僅僅是為了訪問該值,要使用屬性而不 要使用方法
如果該操作每次返回的結(jié)果不同,那么要使用方法。例如來自于.net framework的例子:
//好的寫法
Guid.NewGuid();
//不好的寫法
DateTime.Now;
如果該操作比訪問字段慢一個或多個數(shù)量級,要使用方法。
如果該操作有嚴(yán)重的副作用,要使用方法。
如果不應(yīng)該讓調(diào)用方法改變屬性值,要創(chuàng)建只讀屬性;
′ 不要提供只寫屬性;
要為所有的屬性提供合理的默認(rèn)值,這樣可以確保默認(rèn)值不會導(dǎo)致漏洞或效率低的代 碼;
要允許用戶以任何順序來設(shè)置屬性的值;
避免在屬性的獲取方法拋出異常。
屬性的獲取方法應(yīng)該是個簡單的操作,不應(yīng)該有任何的條件。如果一個獲取方法會拋出 異常,按么可能它更應(yīng)該設(shè)計為方法。
建議提供簡單的構(gòu)造函數(shù),最好是默認(rèn)構(gòu)造函數(shù)。簡單的構(gòu)造函數(shù)增強(qiáng)易用性;
考慮擴(kuò)展性,如果構(gòu)造函數(shù)設(shè)計的不自然,建議用靜態(tài)的工廠方法來替代構(gòu)造函數(shù);
要把構(gòu)造函數(shù)的參數(shù)用作設(shè)置主要屬性的便捷方法。如果構(gòu)造函數(shù)參數(shù)僅用來設(shè)置屬 性,應(yīng)和屬性名稱相同。僅有大小寫的區(qū)別;
要在構(gòu)造函數(shù)中做最少的工作。任何其他處理應(yīng)該推遲到需要的時候;
要在類中顯示的聲明公用的默認(rèn)構(gòu)造函數(shù),如果這樣的構(gòu)造函數(shù)是必須的。
如果沒有顯示默認(rèn)構(gòu)造函數(shù),填加有參數(shù)構(gòu)造函數(shù)時往往會破壞已有使用默認(rèn)構(gòu)造函數(shù) 的代碼;
′ 避免在對象的構(gòu)造函數(shù)內(nèi)部調(diào)用虛成員。這樣在擴(kuò)展設(shè)計的時候會導(dǎo)致難以理解的現(xiàn) 象;
′ 不要提供公有的或受保護(hù)的字段。代之以屬性來訪問字段;
要只用常量字段來表示永遠(yuǎn)不會改變的量。否則會導(dǎo)致兼容性問題。下面是正確的例子:
public struct Int32
{
public const int MaxValue = 0x7fffffff;
public const int MinValue = unchecked((int)0x80000000);
}
要用公有的靜態(tài)只讀字段來定義預(yù)定義的對象實(shí)例。例如:
public struct Color
{
public static readonly Color Red = new Color(0x0000FF);
}
要用類結(jié)構(gòu)層次中最接近基類類型來作為參數(shù)的類型,同時要保證該類型能夠提供成員 所需的功能。例如:
要設(shè)計一個集合遍歷的方法,那么參數(shù)應(yīng)該是IEnbumerable為參數(shù),而不應(yīng)該是IList, 這樣方法具有更強(qiáng)的適應(yīng)性。
′ 不要使用保留參數(shù)。如果將來需要更多的參數(shù),那么可以增加重載成員。例如:
//不好的寫法
public void Method(string reserved, SomeOption option);
//好的寫法
public void Method(SomeOption option);
//將來填加
public void Method(SomeOption option, string path);
要用枚舉。在代碼閱讀,書寫中,枚舉都比布爾的可讀性好很多。例如:
//使用布爾型,閱讀的時候不會輕易了解參數(shù)的含義
FileStream f = File.Open(“1.txt”, true, false);
//使用枚舉型
FileStream f = File.Open(“1.txt”,CasingOptions.CaseSenstive, FileMode.Open);
′ 不要使用布爾參數(shù),除非百分之百肯定絕對不需要兩個以上的值。即使此時,采用枚舉 往往也可以提供更好的可讀性,如上例。
考慮在構(gòu)造函數(shù)中,對確實(shí)只有兩種狀態(tài)值的參數(shù)以及用來初始化布爾屬性的參數(shù)使用 布爾類型;
要驗(yàn)證傳給公有的,受保護(hù)的或顯示成員的參數(shù)是否合法。如果驗(yàn)證失敗,應(yīng)該拋出 System.ArgutmentException或其子類;
要拋出System.ArgutmentNullException,如果傳入的null,而該成員不支持null;
′ 避免使用輸出參數(shù)或引用參數(shù);
′ 如果沒有恰當(dāng)理由,不要把類密封起來。這些理由包括:
A)類為靜態(tài)類;
B)類的受保護(hù)成員保存了高度機(jī)密信息;
C)類繼承了許多虛成員,逐個密封的代價太高,不如密封整個類;
D)不要在密封類中聲明保護(hù)成員或虛成員,因?yàn)闊o法覆蓋其實(shí)現(xiàn);
建議用保護(hù)成員用于高級定制。它提供了擴(kuò)展性,同時也避免了公用接口過于復(fù)雜;
′ 不要使用虛成員,除非有合適的理由;
建議只有在絕對必須的時候才用虛成員提供擴(kuò)展性,并使用Template Method模式;
要優(yōu)先使用受保護(hù)的虛成員,而不是公有虛成員。公有成員通用調(diào)用受保護(hù)的虛成員的方式來提供擴(kuò)展性;
異常的思想是只對錯誤采用異常處理:邏輯和編程錯誤,設(shè)置錯誤,被破壞的數(shù)據(jù),資源耗盡,等等。通常的法則是系統(tǒng)在正常狀態(tài)下以及無重載和硬件失效狀態(tài)下,不應(yīng)產(chǎn)生任何異常。異常處理時可以采用適當(dāng)?shù)娜罩緳C(jī)制來報告異常,包括異常發(fā)生的時刻;
′ 一般情況下不要使用異常實(shí)現(xiàn)來控制程序流程結(jié)構(gòu);
′ 使用異常而不要用錯誤代碼來報告錯誤;
要通過拋出異常的方式來報告操作失敗。如果成員無法成功地完成它應(yīng)該做的任務(wù),那么應(yīng)該拋出異常;
優(yōu)先考慮使用System命名空間中已有的異常,而不是自己創(chuàng)建新的異常類型;
要使用最合理,最具針對性的異常。例如,對參數(shù)為空,應(yīng)拋出 System.ArgutmentNullException,而不是System.ArgutmentException
′ 不是百分之百確定的情況,不要吞掉異常;
建議捕獲特定類型的異常,如果理解該異常在具體環(huán)境當(dāng)中產(chǎn)生的原因;
′ 不要捕獲不應(yīng)該捕獲的異常,通常應(yīng)該允許異常沿著調(diào)用棧傳遞;
進(jìn)行清理工作時要用try-finally,避免使用try-catch;
要在捕獲并重新拋出異常時使用空的throw語句,這是保持調(diào)用棧的最好方法
′ 不要拋出這兩種類型的異常;
′ 避免捕獲這兩種異常,除非是在頂層的異常處理器中;
對象處于不正確狀態(tài)時拋出;
如果傳入的是無效參數(shù),要拋出參數(shù)異常,盡可能使用位于繼承層次末尾的類型;
要在拋出異常時設(shè)置ParaName屬性;
′ 不要顯示拋出或捕獲;
′ 不要顯示拋出或捕獲;
′ 不要顯示拋出或捕獲;
′ 避免太深的繼承層次;
要從已有的異?;惱^承;
異常類要以“Exception”做為后綴;
要使異??尚蛄谢?,使其能跨應(yīng)用程序域和遠(yuǎn)程邊界仍能正常使用;
要把與安全性有關(guān)的信息保存在私有的異常狀態(tài)中
如果在普通場景都會拋出異常,要采用先效驗(yàn)合法性的方式來避免拋出異常引起的性能 問題;
為避免頻繁改動代碼,代碼中只寫比較簡單的和不會經(jīng)常發(fā)生變化的SQL,如果SQL 經(jīng)常發(fā)生變化或是比較復(fù)雜,存到SysMisc中,比如統(tǒng)計用到的SQL;
在VS2005開發(fā)環(huán)境中,采用代碼分析工具來做自動化的代碼分析,以保證代碼質(zhì)量, 具體的使用建議如下:
A)啟用代碼分析,并設(shè)置當(dāng)風(fēng)格不符合要求時為錯誤而不是警告;
B)如果不是做代碼審核,此開關(guān)應(yīng)關(guān)閉。加上了這個選項(xiàng)的時候編譯很慢;
C)詳設(shè)的時候打開開關(guān),檢查詳設(shè)是否符合編程規(guī)范;
D)所有的選項(xiàng)都應(yīng)當(dāng)打開。以下內(nèi)容需要單獨(dú)設(shè)置:
編碼 | 名稱 | 大類 | 建議 | 使用等級 |
CA2209 | 程序集應(yīng)聲明最小安全性 | 用法規(guī)則 | 不建議使用 | 警告 |
CA1814 | 與多維數(shù)組相比,首選使用交錯的數(shù)組 | 性能規(guī)則 | 使用,但降低等級 | 警告 |
CA1822 | 將成員標(biāo)記為 static | 性能規(guī)則 | 較繁鎖,且影響代碼質(zhì)量 | 禁用 |
CA2210 | 程序集應(yīng)具有有效的強(qiáng)名稱 | 設(shè)計規(guī)則 | 影響Xcopy部署 | 禁用 |
CA1302 | 不要對區(qū)域設(shè)置特定的字符串進(jìn)行硬編碼 | 全球化規(guī)則 | 很繁瑣,并且工具支持的不好。全球化規(guī)則全部禁用 | 禁用 |
CA2100 | 檢查 Sql 查詢中是否有安全漏洞 | 安全性規(guī)則 | 都采用參數(shù)化查詢,有可能會參數(shù)過長;如果是內(nèi)部參數(shù),也不會有安全問題 | 警告 |
1,《.NET設(shè)計規(guī)范》,本規(guī)范很多內(nèi)容都參考了這本書,書中對規(guī)范背后的背景和原則做了深入討論;
<逆水行舟,不進(jìn)則退>