.Net Core 編碼規范
標簽: 未分類
概述
規范制定原則
- 方便代碼的交流和維護。
- 不影響編碼的效率,不與大眾習慣沖突。
- 使代碼更美觀、閱讀更方便。
- 使代碼的邏輯更清晰、更易於理解。
術語定義
Pascal 大小寫
將標識符的首字母和后面連接的每個單詞的首字母都大寫。可以對三字符或更多字符的標識符使用Pascal 大小寫。例:
BackColor
Camel 大小寫
標識符的首字母小寫,而每個后面連接的單詞的首字母都大寫。例:
backColor
匈牙利命名法
匈牙利命名法是一名匈牙利程序員發明的,而且他在微軟工作了多年。此命名法就是通過微軟的各種產品和文檔傳出來的。多數有經驗的程序員,不管他們用的是哪門兒語言,都或多或少在使用它。
這種命名法的基本原則是:
變量名=屬性+類型+對象描述
即一個變量名是由三部分信息組成,這樣,程序員很容易理解變量的類型、用途,而且便於記憶。
下邊是一些推薦使用的規則例子,你可以挑選使用,也可以根據個人喜好作些修改再用之。
-
屬性部分:
-
全局變量: g_
-
常量 : c_
-
類成員變量: m_
-
類型部分:
-
指針: p
-
句柄: h
-
布爾型: b
-
浮點型: f
-
無符號: u
-
描述部分:
-
初始化: Init
-
臨時變量: Tmp
-
目的對象: Dst
-
源對象: Src
-
窗口: Wnd
下邊舉例說明:
- hwnd: h表示句柄,wnd表示窗口,合起來為“窗口句柄”。
- m_bFlag: m表示成員變量,b表示布爾,合起來為:“某個類的成員變量,布爾型,是一個狀態標志”。
代碼外觀
列寬
代碼列寬控制在120字符左右。
換行
當表達式超出或即將超出規定的列寬,遵循以下規則進行換行
- 在逗號后換行。
- 在操作符前換行。
- 規則1優先於規則2。
當以上規則會導致代碼混亂的時候自己采取更靈活的換行規則。
縮進
縮進應該是每行一個Tab(4個空格),不要在代碼中使用Tab字符。
Visual Studio 設置:工具->選項->文本編輯器->C#->制表符->插入空格,制表符大小=4,縮進大小=4
空行
空行是為了將邏輯上相關聯的代碼分塊,以便提高代碼的可閱讀性。
在以下情況下使用兩個空行
- 接口和類的定義之間。
- 枚舉和類的定義之間。
- 類與類的定義之間。
在以下情況下使用一個空行
- 方法與方法、屬性與屬性之間。
- 方法中變量聲明與語句之間。
- 方法與方法之間。
- 方法中不同的邏輯塊之間。
- 方法中的返回語句與其他的語句之間。
- 屬性與方法、屬性與字段、方法與字段之間。
- 注釋與它注釋的語句間不空行,但與其他的語句間空一行。
空格
在以下情況中要使用到空格
- 關鍵字和左括符 “(” 應該用空格隔開。如:
while (true)
注意在方法名和左括符 “(” 之間不要使用空格,這樣有助於辨認代碼中的方法調用與關鍵字。
- 多個參數用逗號隔開,每個逗號后都應加一個空格。
- 除了 . 之外,所有的二元操作符都應用空格與它們的操作數隔開。一元操作符、++及--與操作數間不需要空格。如:
a += c + d;
a = (a + b)/(c*d);
while (d++ == s++)
{
n++;
}
PrintSize("size is " + size + "\n");
- 語句中的表達式之間用空格隔開。如:
for (expr1; expr2; expr3)
括號 - ()
- 左括號“(”不要緊靠關鍵字,中間用一個空格隔開。
- 左括號“(”與方法名之間不要添加任何空格。
- 沒有必要的話不要在返回語句中使用()。
花括號 - {}
- 左花括號 “{” 放於關鍵字或方法名的下一行並與之對齊。如:
if (condition)
{
}
public int Add(int x, int y)
{
}
- 左花括號 “{” 要與相應的右花括號 “}”對齊。
- 通常情況下左花括號 “{”單獨成行,不與任何語句並列一行。
- if、while、do語句后一定要使用{},即使{}號中為空或只有一條語句。如:
if (somevalue == 1)
{
somevalue = 2;
}
- 右花括號 “}” 后建議加一個注釋以便於方便的找到與之相應的 {。如:
while(1)
{
if(valid)
{
} // if valid
else
{
} // not valid
} // end forever
程序注釋
注釋概述
- 修改代碼時,總是使代碼周圍的注釋保持最新。
- 在每個例程的開始,提供標准的注釋樣本以指示例程的用途、假設和限制很有幫助。注釋樣本應該是解釋它為什么存在和可以做什么的簡短介紹.
- 避免在代碼行的末尾添加注釋;行尾注釋使代碼更難閱讀。不過在批注變量聲明時,行尾注釋是合適的;在這種情況下,將所有行尾注釋在公共制表位處對齊。
- 避免雜亂的注釋,如一整行星號。而是應該使用空白將注釋同代碼分開。
- 避免在塊注釋的周圍加上印刷框。這樣看起來可能很漂亮,但是難於維護。
- 在部署發布之前,移除所有臨時或無關的注釋,以避免在日后的維護工作中產生混亂。
- 如果需要用注釋來解釋復雜的代碼節,請檢查此代碼以確定是否應該重寫它。盡一切可能不注釋難以理解的代碼,而應該重寫它。盡管一般不應該為了使代碼更簡單以便於人們使用而犧牲性能,但必須保持性能和可維護性之間的平衡。
- 在編寫代碼時就注釋,因為以后很可能沒有時間這樣做。另外,如果有機會復查已編寫的代碼,在今天看來很明顯的東西六周以后或許就不明顯了。
- 避免多余的或不適當的注釋,不應包含個人情緒內容,如幽默的不主要的備注。
- 在編寫注釋時使用完整的句子。注釋應該闡明代碼,而不應該增加多義性。
- 使用注釋來解釋代碼的意圖。它們不應作為代碼的聯機翻譯。
- 注釋代碼中不十分明顯的內容。
- 為了防止問題反復出現,對錯誤修復和解決方法代碼總是使用注釋。
- 對由循環和邏輯分支組成的代碼使用注釋。這些是幫助源代碼讀者的主要方面。
- 在整個應用程序中,使用具有一致的標點和結構的統一樣式來構造注釋。
- 用空白將注釋同注釋分隔符分開。在沒有顏色提示的情況下查看注釋時,這樣做會使注釋很明顯且容易被找到。
- 代碼修改變更記錄不應使用注釋標明修改日期和修改人,注釋應只針對代碼不記錄版本,代碼版本應該使用代碼版本系統進行管理
- 為了使層次清晰,在閉合的右花括號后注釋該閉合所對應的起點。
namespace SCB.Framework.Web
{
} // namespace SCB.Framework.Web
文檔型注釋
該類注釋采用.Net已定義好的Xml標簽來標記,在聲明接口、類、方法、屬性、字段都應該使用該類注釋,以便代碼完成后直接生成代碼文檔,讓別人更好的了解代碼的實現和接口。如
/// <summary> MyMethod is a method in the MyClass class.
/// <para> Here's how you could make a second paragraph in a description.
/// <see cref="System.Console.WriteLine"/>
/// for information about output statements.
/// </para>
/// <seealso cref="MyClass.Main"/>
/// </summary>
public static void MyMethod(int Int1)
{
}
注釋標簽的使用請參考:http://msdn.microsoft.com/zh-cn/library/5ast78ax.aspx
類c注釋
該類注釋用於
- 復雜程序邏輯說明與技術事項
用法
/*
動態路由算法使用Round-robin算法,原理是...
*/
單行注釋
該類注釋用於
- 方法內的代碼注釋。如變量的聲明、代碼或代碼段的解釋。例:
//
// 注釋語句
//
private int number;
或
// 注釋語句
private int number;
- 方法內變量的聲明或花括號后的注釋, 例:
if (1 == 1) // always true
{
statement;
} // always true
聲明
每行聲明數
一行只建議作一個聲明,並按字母順序排列。如:
int level; // 推薦
int size; // 推薦
int x, y; // 不推薦
初始化
建議在變量聲明時就對其做初始化。
位置
變量建議置於塊的開始處,不要總是在第一次使用它們的地方做聲明。如:
void MyMethod()
{
int int1 = 0;
if (condition)
{
int int2 = 0;
...
}
}
例外情況
for (int i = 0; i < maxLoops; i++)
{
...
}
應避免不同層次間的變量重名,如:
int count;
...
void MyMethod()
{
if (condition)
{
int count = 0; // 避免
...
}
...
}
類和接口的聲明
- 在方法名與其后的左括號間沒有任何空格。
- 左花括號 “{” 出現在聲明的下行並與之對齊,單獨成行。
- 方法間用一個空行隔開。
字段的聲明
不要使用是 public 或 protected 的實例字段。如果避免將字段直接公開給開發人員,可以更輕松地對類進行版本控制,原因是在維護二進制兼容性時字段不能被更改為屬性。考慮為字段提供 get 和set 屬性訪問器,而不是使它們成為公共的。 get 和 set 屬性訪問器中可執行代碼的存在使得可以進行后續改進,如在使用屬性或者得到屬性更改通知時根據需要創建對象。下面的代碼示例闡釋帶有 get 和 set 屬性訪問器的私有實例字段的正確使用。例:
public class Control: Component
{
private int handle;
public int Handle
{
get
{
return handle;
}
}
}
命名規范
命名概述
名稱應該說明“什么”而不是“如何”。通過避免使用公開基礎實現(它們會發生改變)的名稱,可以保留簡化復雜性的抽象層。例如,可以使用
GetNextStudent(),而不是GetNextArrayElement()。
命名原則是:
選擇正確名稱時的困難可能表明需要進一步分析或定義項的目的。使名稱足夠長以便有一定的意義,並且足夠短以避免冗長。唯一名稱在編程上僅用於將各項區分開。表現力強的名稱是為了幫助人們閱讀;因此,提供人們可以理解的名稱是有意義的。不過,請確保選擇的名稱符合適用語言的規則和標准。
以下幾點是推薦的命名方法:
- 避免容易被主觀解釋的難懂的名稱,如方面名
AnalyzeThis(),或者屬性名xxK8。這樣的名稱會導致多義性。 - 在類屬性的名稱中包含類名是多余的,如
Book.BookTitle。而是應該使用Book.Title。 - 只要合適,在變量名的末尾或開頭加計算限定符
(Avg、Sum、Min、Max、Index)。 - 在變量名中使用互補對,如
min/max、begin/end和open/close。 - 布爾變量名應該包含
Is,這意味着Yes/No或True/False值,如fileIsFound。 - 在命名狀態變量時,避免使用諸如
Flag的術語。狀態變量不同於布爾變量的地方是它可以具有兩個以上的可能值。不是使用documentFlag,而是使用更具描述性的名稱,如documentFormatType。 - 即使對於可能僅出現在幾個代碼行中的生存期很短的變量,仍然使用有意義的名稱。僅對於短循環索引使用單字母變量名,如 i 或 j。 可能的情況下,盡量不要使用原義數字(幻數)或原義字符串,如
for (int i = 1; i < 7; i++)。而是使用命名常數,如for (int i = 1; i < NUM_DAYS_IN_WEEK; i++)以便於維護和理解。
大小寫規則
大寫
- 組織名縮寫使用大寫
- 兩個或者更少字母組成的標識符使用大寫。例:
System.IO
System.Web.UI
SCB.Framework.UI
下表匯總了大寫規則,並提供了不同類型的標識符的示例。
| 標識符 | 大小寫 | 示例 |
|---|---|---|
| 類 | Pascal | AppDomain |
| 枚舉類型 | Pascal | ErrorLevel |
| 枚舉值 | Pascal | FatalError |
| 事件 | Pascal | ValueChange |
| 異常類 | Pascal | WebException 注意: 總是以 Exception 后綴結尾。 |
| 只讀的靜態字段 | Pascal | RedValue |
| 接口 | Pascal | IDisposable 注意: 總是以 I 前綴開始。 |
| 方法 | Pascal | ToString |
| 命名空間 | Pascal | System.Drawing |
| 屬性 | Pascal | BackColor |
| 公共實例字段 | Pascal | RedValue 注意: 應優先使用屬性。 |
| 受保護的實例字段 | Camel | redValue 注意: 應優先使用屬性。 |
| 私有的實例字段 | Camel | redValue |
| 參數 | Camel | typeName |
| 方法內的變量 | Camel | backColor |
縮寫
為了避免混淆和保證跨語言交互操作,請遵循有關區縮寫的使用的下列規則:
- 不要將縮寫或縮略形式用作標識符名稱的組成部分。例如,使用
GetWindow,而不要使用GetWin。 - 不要使用計算機領域中未被普遍接受的縮寫。
- 在適當的時候,使用眾所周知的縮寫替換冗長的詞組名稱。例如,用
UI作為User Interface縮
寫,用OLAP作為On-line Analytical Processing的縮寫。 - 在使用縮寫時,對於超過兩個字符長度的縮寫請使用 Pascal 大小寫或 Camel 大小寫。例如使用
HtmlButton或HTMLButton;但是,應當大寫僅有兩個字符的縮寫,如:System.IO,而不是System.Io。 - 不要在標識符或參數名稱中使用縮寫。如果必須使用縮寫,對於由多於兩個字符所組成的縮寫請使用Camel 大小寫。
命名空間
- 命名命名空間時的一般性規則是使用公司名稱,后跟技術名稱和可選的功能與設計,如:
CompanyName.TechnologyName[.Feature][.Design]
例如:
namespace SCB.SupplierChain // 賽酷比公司的供應鏈系統
namespace SCB.SupplierChain.DataRules // 賽酷比公司的供應鏈系統的業務規則模塊
- 命名空間使用Pascal大小寫。
TechnologyName指的是該項目的英文縮寫或軟件名。- 命名空間和類不能使用同樣的名字。例如,有一個類被命名為
Debug后,就不要再使用Debug作為一個名稱空間名。
類
- 使用 Pascal 大小寫。
- 用名詞或名詞短語命名類。
- 使用全稱避免縮寫,除非縮寫已是一種公認的約定,如
URL、HTML - 不要使用類型前綴,如在類名稱上對類使用 C 前綴。例如,使用類名稱
FileStream,而不是
CFileStream。 - 不要使用下划線字符 (_)。
- 有時候需要提供以字母 I 開始的類名稱,雖然該類不是接口。只要 I 是作為類名稱組成部分的整個單詞的第一個字母,這便是適當的。例如,類名稱
IdentityStore是適當的。在適當的地方,使用復合單詞命名派生的類。派生類名稱的第二個部分應當是基類的名稱。例如,ApplicationException對於從名為Exception的類派生的類是適當的名稱,原因ApplicationException是一種Exception。請在應用該規則時進行合理的判斷。例如,Button對於從Control派生的類是適當的名稱。盡管按鈕是一種控件,但是將Control作為類名稱的一部分將使名稱不必要地加長。
public class FileStream
public class Button
public class String
接口
- 用名詞或名詞短語,或者描述行為的形容詞命名接口。例:
- 接口名稱
IComponent使用描述性名詞 - 接口名稱
ICustomAttributeProvider使用名詞短語 - 接口名稱
IPersistable使用形容詞。
- 接口名稱
- 使用 Pascal 大小寫。
- 少用縮寫。
- 給接口名稱加上字母 I 前綴,以指示該類型為接口。在定義類/接口對(其中類是接口的標准實現)時使用相似的名稱。兩個名稱的區別應該只是接口名稱上有字母 I 前綴。
- 不要使用下划線字符 (_)。
public interface IServiceProvider
public interface IFormatable
以下代碼示例闡釋如何定義 IComponent 接口及其標准實現 Component 類。
public interface IComponent
{
// Implementation code goes here.
}
public class Component: IComponent
{
// Implementation code goes here.
}
屬性類 (Attribute)
應該總是將后綴 Attribute 添加到自定義屬性類。例:
public class ObsoleteAttribute
{
}
枚舉 (Enum)
枚舉 (Enum) 值類型從 Enum 類繼承。
- 對於 Enum 類型和值名稱使用 Pascal 大小寫。
- 少用縮寫。
- 不要在 Enum 類型名稱上使用 Enum 后綴。
- 對大多數 Enum 類型使用單數名稱,但是對作為位域的 Enum 類型使用復數名稱。
- 總是將
FlagsAttribute添加到位域 Enum 類型。
參數
- 使用描述性參數名稱。參數名稱應當具有足夠的描述性,以便參數的名稱及其類型可用於在大多數情況下確定它的含義。
- 對參數名稱使用 Camel 大小寫。
- 使用描述參數的含義的名稱,而不要使用描述參數的類型的名稱。開發工具將提供有關參數的類型的有意義的信息。因此,通過描述意義,可以更好地使用參數的名稱。
- 不要給參數名稱加匈牙利語類型表示法的前綴,僅在適合使用它們的地方使用它們。
- 不要使用保留的參數。保留的參數是專用參數,如果需要,可以在未來的版本中公開它們。相反,如果在類庫的未來版本中需要更多的數據,請為方法添加新的重載。
Type GetType(string typeName)
string Format(string format, object args)
方法
- 使用動詞或動詞短語命名方法。
- 使用 Pascal 大小寫。
RemoveAll()
GetCharArray()
Invoke()
屬性 (property)
- 使用名詞或名詞短語命名屬性。
- 使用 Pascal 大小寫。
- 考慮用與屬性的基礎類型相同的名稱創建屬性。例如,如果聲明名為
Color的屬性,則屬
性的類型同樣應該是 Color。
public class SampleClass
{
public Color BackColor
{
// Code for Get and Set accessors goes here.
}
}
以下代碼示例闡釋提供其名稱與類型相同的屬性。
public enum Color
{
// Insert code for Enum here.
}
public class Control
{
public Color Color
{
get
{
// Insert code here.
}
set
{
// Insert code here.
}
}
}
事件
- 對事件處理程序名稱使用
EventHandler后綴。 - 指定兩個名為
sender和e的參數。sender參數表示引發事件的對象。sender參數始
終是object類型的,即使在可以使用更為特定的類型時也如此。與事件相關聯的狀態封裝
在名為e的事件類的實例中。對e參數類型使用適當而特定的事件類。 - 用
EventArgs后綴命名事件參數類。 - 考慮用動詞命名事件。
- 使用動名詞(動詞的“ing”形式)創建表示事件前的概念的事件名稱,用過去式表示事
件后。例如,可以取消的Close事件應當具有Closing事件和Closed事件。不要使用
BeforeXxx/AfterXxx命名模式。 - 不要在類型的事件聲明上使用前綴或者后綴。例如,使用
Close,而不要使用OnClose。 - 通常情況下,對於可以在派生類中重寫的事件,應在類型上提供一個受保護的方法(稱為
OnXxx)。此方法只應具有事件參數e,因為發送方總是類型的實例。
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
public class MouseEventArgs : EventArgs
{
int x;
int y;
public MouseEventArgs(int x, int y)
{
this.x = x;
this.y = y;
}
public int X
{
get
{
return x;
}
}
public int Y
{
get
{
return y;
}
}
}
常量 (const)
所有單詞大寫,多個單詞之間用 "_" 隔開。 如:
public const string PAGE_TITLE = "Welcome";
字段
- private、protected 使用 Camel 大小寫。
- public 使用 Pascal 大小寫。
- 拼寫出字段名稱中使用的所有單詞。僅在開發人員一般都能理解時使用縮寫。
class SampleClass
{
string url;
string destinationUrl;
}
- 不要對字段名使用匈牙利語表示法。好的名稱描述語義,而非類型。
- 不要對字段名或靜態字段名應用前綴。具體說來,不要對字段名稱應用前綴來區分靜態和非靜態字段。例如,應用
g_或s_前綴是不正確的。 - 對預定義對象實例使用公共靜態只讀字段。如果存在對象的預定義實例,則將它們聲明為
對象本身的公共靜態只讀字段。使用 Pascal 大小寫,原因是字段是公共的。
public struct Color
{
public static readonly Color Red = new Color(0x0000FF);
public Color(int rgb)
{
// Insert code here.
}
public Color(byte r, byte g, byte b)
{
// Insert code here.
}
public byte RedValue
{
get
{
return Color;
}
}
}
靜態字段
- 使用名詞、名詞短語或者名詞的縮寫命名靜態字段。
- 使用 Pascal 大小寫。
- 建議盡可能使用靜態屬性而不是公共靜態字段。
集合
集合是一組組合在一起的類似的類型化對象,如哈希表、查詢、堆棧、字典和列表,集合的命名建議用復數。
措詞
避免使用與常用的 .NET 框架命名空間重復的類名稱。例如,不要將以下任何名稱用作類名稱:System、Collections、Forms 或 UI。有關 .NET 框架命名空間的列表,請參閱類庫。
另外,避免使用與C#語言關鍵字沖突的標識符。
語句
每行一個語句
每行最多包含一個語句。如:
a++; // 推薦
b--; // 推薦
a++; b--; // 不推薦
復合語句
復合語句是指包含"父語句{子語句;子語句;}"的語句,使用復合語句應遵循以下幾點
- 子語句要縮進。
- 左花括號“{” 在復合語句父語句的下一行並與之對齊,單獨成行。
- 即使只有一條子語句要不要省略花括號“ {}”。 如:
while(d += s++)
{
n++;
}
return 語句
return語句中不使用括號,除非它能使返回值更加清晰。如:
return;
return myDisk.size();
return (size ? size : defaultSize);
if、 if-else、if else-if 語句
if、 if-else、if else-if 語句使用格式
if (condition)
{
statements;
}
if (condition)
{
statements;
}
else
{
statements;
}
if (condition)
{
statements;
}
else if (condition)
{
statements;
}
else
{
statements;
}
for、foreach 語句
for 語句使用格式
for (initialization; condition; update)
{
statements;
}
空的 for 語句(所有的操作都在initialization、condition 或 update中實現)使用格式
for (initialization; condition; update); // update user id
foreach 語句使用格式
foreach (object obj in array)
{
statements;
}
注意
- 在循環過程中不要修改循環計數器。
- 對每個空循環體給出確認性注釋。
while 語句
while 語句使用格式
while (condition)
{
statements;
}
空的 while 語句使用格式
while (condition);
do - while 語句
do - while 語句使用格式
do
{
statements;
} while (condition);
switch - case 語句
switch - case語句使用格式
switch (condition)
{
case 1:
statements;
break;
case 2:
statements;
break;
default:
statements;
break;
}
注意:
- 語句switch中的每個case各占一行。
- 為所有switch語句提供default分支。
- 所有的非空 case 語句必須用 break; 語句結束。
try - catch 語句
try - catch語句使用格式
try
{
statements;
}
catch (ExceptionClass e)
{
statements;
}
finally
{
statements;
}
using 塊語句
using 塊語句使用格式
using (object)
{
statements;
}
控件命名規則
命名方法
控件名簡寫+英文描述,英文描述首字母大寫
主要控件名簡寫對照表
- 控件名 => 簡寫
- Label => lbl
- TextBox => txt
- Button => btn
- LinkButton => lnkbtn
- ImageButton => imgbtn
- DropDownList => ddl
- ListBox => lst
- DataGrid => dg
- DataList => dl
- CheckBox => chk
- CheckBoxList => chkls
- RadioButton => rdo
- RadioButtonList => rdolt
- Image => img
- Panel => pnl
- Calender => cld
- AdRotator => ar
- Table => tbl
- RequiredFieldValidator => rfv
- CompareValidator => cv
- RangeValidator => rv
- RegularExpressionValidator => rev
- ValidatorSummary => vs
- CrystalReportViewer => rptvew
其他
表達式
- 避免在表達式中用賦值語句
- 避免對浮點類型做等於或不等於判斷
類型轉換
- 盡量避免強制類型轉換。
- 如果不得不做類型轉換,盡量用顯式方式。
