第1章程序的版式
版式雖然不會影響程序的功能,但會影響可讀性。程序的版式追求清晰、美觀,是程序風格的重要構成因素。
可以把程序的版式比喻為"書法"。好的"書法"可讓人對程序一目了然,看得興致勃勃。差的程序"書法"如螃蟹爬行,讓人看得索然無味,更令維護者煩惱有加。
1.1 版本和版權聲明
版本和版權的聲明寫在文件的開頭,包含內容如下:
1、版權信息
2、摘要
3、當前版本
4、作者
5、修改作者
6、完成日期
7、版本歷史信息
例:
///<copyright> Copyright (c) 2006,有限公司</copyright>
///<copyright> All rights reserved.</copyright>
///<abstract>描述文件的內容,實現的功能和算法等內容</abstract>
///<current_version>當前版本</current_version>
///<author>作者</author>
///<finish_date>完成日期</finish_date>
///<replace_version>取代版本</replace_version>
///<modify>修改</modify>
///<modify_author>修改作者</modify_author>
///<modify_date>修改日期</modify_date>
版本版權聲明示例
在C#中代碼注釋這樣寫的好處是Visual Stuidio能夠在編譯的時候自動生成xml格式的注釋文檔。
1.2空行
空行起著分隔程序段落的作用。空行得體(不過多也不過少)將使程序的布局更加清晰。空行不會浪費內存,雖然打印含有空行的程序是會多消耗一些紙張,但是值得。所以不要捨不得用空行。
在每個類聲明之後、每個函數定義結束之後都要加空行。參見示例1-2(a)在一個函數體內,邏揖上密切相關的語句之間不加空行,其它地方應加空行分隔。參見示例1-2(b )
// 空行
void Function1(…)
{
…
}
// 空行
void Function2(…)
{
…
}
// 空行
void Function3(…)
{
…
}
// 空行
while (condition)
{
statement1;
// 空行
if (condition)
{
statement2;
}
else
{
statement3;
}
// 空行
statement4;
}
示例1-2(a) 函數之間的空行 示例1-2(b) 函數內部的空行
1.3 代碼行
(1)一行代碼只做一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,並且方便於寫注釋。
(2)if、for、while、do等語句自占一行,執行語句不得緊跟其後。不論執行語句有多少都要加{}。這樣可以防止書寫失誤。
示例1-3(a)為風格良好的代碼行,示例1-3(b)為風格不良的代碼行。
int width; // 寬度
int height; // 高度
int depth; // 深度
int width, height, depth;
// 寬度高度深度
x = a + b;
y = c + d;
z = e + f;
X = a + b; y = c + d; z = e + f;
if (width < height)
{
dosomething();
}
if (width < height) dosomething();
for (initialization; condition; update)
{
dosomething();
}
// 空行
other();
for (initialization; condition; update)
dosomething();
other();
示例1-3(a) 風格良好的代碼行 示例1-3(b) 風格不良的代碼行
【建議】盡可能在定義變量的同時初始化該變量(就近原則)
如果變量的引用處和其定義處相隔比較遠,變量的初始化很容易被忘記。如果引用了未被初始化的變量,可能會導致程序錯誤。本建議可以減少隱患。例如
int width = 10; // 定義並初绐化width
int height = 10; // 定義並初绐化height
int depth = 10; // 定義並初绐化depth
1.4 代碼行內的空格
(1)關鍵字之後要留空格。象const、case 等關鍵字之後至少要留一個空格,否則無法辨析關鍵字。象if、for、while等關鍵字之後應留一個空格再跟左括號'(',以突出關鍵字。
(2)函數名之後不要留空格,緊跟左括號'(',以與關鍵字區別。
(3)'('向後緊跟,')'、','、';'向前緊跟,緊跟處不留空格。
(4)','之後要留空格,如Function(x, y, z)。如果';'不是一行的結束符號,其後要留空格,如for (initialization; condition; update)。
(5)賦值操作符、比較操作符、算術操作符、邏輯操作符、位域操作符,如"="、"+=" ">="、"<="、"+"、"*"、"%"、"&&"、"||"、"<<","^"等二元操作符的前後應當加空格。
(6)一元操作符如"!"、"~"、"++"、"--"、"&"(地址運算符)等前後不加空格。
(7)象"[]"、"."、"->"這類操作符前後不加空格。
(8)對於表達式比較長的for語句和if語句,為了緊湊起見可以適當地去掉一些空格,如for (i=0; i<10; i++)和if ((a<=b) && (c<=d))
示例1-4 代碼行內的空格
void Func1(int x, int y, int z)
void Func1 (int x,int y,int z)
if (year >= 2000)
if(year>=2000)
if ((a>=b) && (c<=d))
if(a>=b&&c<=d)
for (i=0; i<10; i++)
for(i=0;i<10;i++)
x = a < b ? a : b;
x=a<b?a:b;
示例1-4(a) 風格良好的代碼行 示例1-4(b) 風格不良的代碼行
1.5 對齊
(1)程序的分界符'{'和'}'應獨占一行並且位於同一列,同時與引用它們的語句左對齊。
(2){ }之內的代碼塊在'{'右邊數格處左對齊。
void Function(int x)
{
… // program code
}
void Function(int x){
… // program code
}
if (condition)
{
… // program code
}
else
{
… // program code
}
if (condition){
… // program code
}
else {
… // program code
}
for (initialization; condition; update)
{
… // program code
}
for (initialization; condition; update){
… // program code
}
While (condition)
{
… // program code
}
while (condition){
… // program code
}
如果出現嵌套的{},則使用縮進對齊,如:
{
…
{
…
}
…
}
示例1-5(a) 風格良好的對齊 示例1-5(b) 風格不良的對齊
1.6長行拆分
代碼行最大長度宜控制在70至80個字符以內。代碼行不要過長,否則眼睛看不過來,也不便於打印。
長表達式要在低優先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當的縮進,使排版整齊,語句可讀。
if ((very_longer_variable1 >= very_longer_variable12)
&& (very_longer_variable3 <= very_longer_variable14)
&& (very_longer_variable5 <= very_longer_variable16))
{
dosomething();
}
for (very_longer_initialization;
very_longer_condition;
very_longer_update)
{
dosomething();
}
示例1-6 長行的拆分
1.7 注釋
C#語言中,程序塊的注釋常采用"/*…*/",行注釋一般采用"//…"。注釋通常用於:
(1)版本、版權聲明;
(2)函數接口說明;
(3)重要的代碼行或段落提示。
(4) 雖然注釋有助於理解代碼,但注意不可過多地使用注釋。
(5)注釋是對代碼的"提示",而不是文檔。程序中的注釋不可喧賓奪主,注釋太多了會讓人眼花缭亂。注釋的花樣要少。
(6)如果代碼本來就是清楚的,則不必加注釋。否則多此一舉,令人厭煩。例如
i++; // i 加 1,多余的注釋
(7)邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
(8)注釋應當准確、易懂,防止注釋有二義性。錯誤的注釋不但無益反而有害。
(9)盡量避免在注釋中使用縮寫,特別是不常用縮寫。
(10)注釋的位置應與被描述的代碼相鄰,可以放在代碼的上方或右方,不可放在下方。
(11)當代碼比較長,特別是有多重嵌套時,應當在一些段落的結束處加注釋,便於閱讀。
/*
* 函數介紹:
* 輸入參數:
* 輸出參數:
* 返回值 :
*/
void Function(float x, float y, float z)
{
…
}
if (…)
{
…
while (…)
{
…
} // end of while
…
} // end of if
示例1-7 程序的注釋
第2章命名規則
所有標識符的命名必須遵循如下三種大小寫規范進行命名:
風格
說明
樣例
Pascal 大小寫
首字母大寫,且後續單詞的首字母都必須大寫;
本規則一般用於三個或更多字母的標識 的情況
BackColor
Camel 大小寫
首字母小寫,且後續單詞的首字母都必須大寫;
本規則僅用於函數參數和保護實例成員的命名中
backColor
大寫格
所有字母都必須大寫
本規則僅用於標識只有兩個或更少字母的情況
System.IO
System.Web.UI
2.1 大小寫規則
大寫標識符中的所有字母都大寫。僅對於由兩個或者更少字母組成的標識符使用該約定。例如:
System.IO
System.Web.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
2.2縮寫
為了避免混淆和保證跨語言交互操作,請遵循有關區縮寫的使用的下列規則:
(1) 不要將縮寫或縮略形式用作標識符名稱的組成部分。例如,使用 GetWindow,而不要使用 GetWin。
(2) 不要使用計算機領域中未被普遍接受的縮寫。
(3) 在適當的時候,使用眾所周知的縮寫替換冗長的詞組名稱。例如,用 UI 作為 User Interface 縮寫,用 OLAP 作為 On-line Analytical Processing 的縮寫。
(4) 在使用縮寫時,對於超過兩個字符長度的縮寫請使用 Pascal 大小寫或 Camel 大寫。例如,使用 HtmlButton 或HTMLButton。但是,應當大寫僅有兩個字符的縮寫,如,System.IO,而不是 System.Io。
(5) 不要在標識符或參數名稱中使用縮寫。如果必須使用縮寫,對於由多於兩個字符所組成的縮寫請使用Camel 大小寫,雖然這和單詞的標准縮寫相沖突。
2.3命名空間
(1) 命名命名空間時的一般性規則是使用公司名稱,後跟技術名稱和可選的功能與設計,如下所示。
CompanyName.TechnologyName[.Feature][.Design]
例如:
namespace Langchao.Procurement
namespace Langchao.Procurement.DataRules
(2) 命名空間使用Pascal大小寫,用逗號分隔開。
(3) TechnologyName 指的是該項目的英文縮寫,或軟件名。
(4) 命名空間和類不能使用同樣的名字。例如,有一個類被命名為Debug後,就不要再
使用Debug作為一個名稱空間名。
2.4類
(1) 使用 Pascal 大小寫。
(2) 用名詞或名詞短語命名類。
(3) 使用全稱避免縮寫,除非縮寫已是一種公認的約定,如URL、HTML
(4) 不要使用類型前綴。例如,使用類名稱 FileStream
(5) 不要使用下劃線字符 (_)。
(6) 有時候需要提供以字母 I 開始的類名稱,雖然該類不是接口。只要 I 是作為類名稱組成部分的整個單詞的第一個字母,這便是適當的。例如,類名稱 IdentityStore 是適當的。在適當的地方,使用復合單詞命名派生的類。派生類名稱的第二個部分應當是基類的名稱。例如,ApplicationException 對於從名為 Exception 的類派生的類是適當的名稱,原因ApplicationException 是一種Exception。請在應用該規則時進行合理的判斷。例如,Button 對於從 Control 派生的類是適當的名稱。盡管按鈕是一種控件,但是將 Control 作為類名稱的一部分將使名稱不必要地加長。
public class FileStream
public class Button
public class String
2.5接口
以下規則概述接口的命名指南:
(1) 用名詞或名詞短語,或者描述行為的形容詞命名接口。例如,接口名稱 IComponent 使用描述性名詞。接口名稱ICustomAttributeProvider 使用名詞短語。名稱 IPersistable 使用形容詞。
(2) 使用 Pascal 大小寫。
(3) 少用縮寫。
(4) 給接口名稱加上字母 I 前綴,以指示該類型為接口。在定義類/接口對(其中類是接口的標准實現)時使用相似的名稱。兩個名稱的區別應該只是接口名稱上有字母 I 前綴。
(5) 不要使用下劃線字符 (_)。
(6) 當類是接口的標准執行時,定義這一對類/接口組合就要使用相似的名稱。兩個名稱的不同之處只是接口名前有一個I前綴。
以下是正確命名的接口的示例。
public interface IServiceProvider
public interface IFormatable
以下代碼示例闡釋如何定義 IComponent 接口及其標准實現 Component 類。
public interface IComponent
{
// Implementation code goes here.
}
public class Component: IComponent
{
// Implementation code goes here.
}
2.6屬性 (Attribute)
應該總是將後綴 Attribute 添加到自定義屬性類。以下是正確命名的屬性類的示例。
public class ObsoleteAttribute
{
}
2.7枚舉 (Enum)
枚舉 (Enum) 值類型從 Enum 類繼承。以下規則概述枚舉的命名指南:
(1) 對於 Enum 類型和值名稱使用 Pascal 大小寫。
(2) 少用縮寫。
(3) 不要在 Enum 類型名稱上使用 Enum 後綴。
(4) 對大多數 Enum 類型使用單數名稱,但是對作為位域的 Enum 類型使用復數名稱。
(5) 總是將 FlagsAttribute 添加到位域 Enum 類型。
2.8參數
以下規則概述參數的命名指南:
(1) 使用描述性參數名稱。參數名稱應當具有足夠的描述性,以便參數的名稱及其類型
可用於在大多數情況下確定它的含義。
(2) 對參數名稱使用 Camel 大小寫。
(3) 使用描述參數的含義的名稱,而不要使用描述參數的類型的名稱。開發工具將提
供有關參數的類型的有意義的信息。因此,通過描述意義,可以更好地使用參
數的名稱。少用基於類型的參數名稱,僅在適合使用它們的地方使用它們。
(4) 不要使用保留的參數。保留的參數是專用參數,如果需要,可以在未來的版本中公
開它們。相反,如果在類庫的未來版本中需要更多的數據,請為方法添加新的重載。
(5) 不要給參數名稱加匈牙利語類型表示法的前綴。
以下是正確命名的參數的示例。
Type GetType(string typeName)
string Format(string format, args() As object)
2.9方法
以下規則概述方法的命名指南:
(1) 使用動詞或動詞短語命名方法。
(2) 使用 Pascal 大小寫。
(3) 以下是正確命名的方法的實例。
RemoveAll()
GetCharArray()
Invoke()
2.10 屬性 (property)
以下規則概述屬性的命名指南:
(1) 使用名詞或名詞短語命名屬性。
(2) 使用 Pascal 大小寫。
(3) 不要使用匈牙利語表示法。
(4) 考慮用與屬性的基礎類型相同的名稱創建屬性。例如,如果聲明名為 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.
}
}
}
以下代碼示例不正確,原因是 Color 屬性是 Integer 類型的。
public enum Color
{
// Insert code for Enum here.
}
public class Control
{
public int Color
{
// Insert code here
}
}
在不正確的示例中,不可能引用 Color 枚舉的成員。Color.Xxx 將被解釋為訪問一個成員,
該成員首先獲取 Color 屬性( C# 中為 int 類型)的值,然後再訪問該值的某個成員(該成
員必須是 System.Int32 的實例成員)。
2.11事件
以下規則概述事件的命名指南:
(1) 對事件處理程序名稱使用 EventHandler 後綴。
(2) 指定兩個名為 sender 和 e 的參數。sender 參數表示引發事件的對象。sender 參數始終是object 類型的,即使在可以使用更為特定的類型時也如此。與事件相關聯的狀態封裝在名為 e 的事件類的實例中。對 e 參數類型使用適當而特定的事件類。
(3) 用 EventArgs 後綴命名事件參數類。
(4) 考慮用動詞命名事件。
(5) 使用動名詞(動詞的"ing"形式)創建表示事件前的概念的事件名稱,用過去式表示事件後。例如,可以取消的 Close 事件應當具有 Closing 事件和 Closed 事件。不要使用BeforeXxx/AfterXxx 命名模式。
(6) 不要在類型的事件聲明上使用前綴或者後綴。例如,使用 Close,而不要使用 OnClose。
(7) 通常情況下,對於可以在派生類中重寫的事件,應在類型上提供一個受保護的方法(稱為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;
}
}
}
2.12 常量 (const)
以下規則概述常量的命名指南:
所有單詞大寫,多個單詞之間用 "_" 隔開。如
public const string PAGE_TITLE = "Welcome";
2.13 字段
以下規則概述字段的命名指南:
(1) private、protected 使用 Camel 大小寫。
(2) public 使用 Pascal 大小寫。
(3) 拼寫出字段名稱中使用的所有單詞。僅在開發人員一般都能理解時使用縮寫。字段名稱不要使用大寫字母。下面是正確命名的字段的示例。
class SampleClass
{
string url;
string destinationUrl;
}
(4) 不要對字段名使用匈牙利語表示法。好的名稱描述語義,而非類型。
(5) 不要對字段名或靜態字段名應用前綴。具體說來,不要對字段名稱應用前綴來區分靜態和非靜態字段。例如,應用 g_ 或s_ 前綴是不正確的。
(6)對預定義對象實例使用公共靜態只讀字段。如果存在對象的預定義實例,則將它們聲明為對象本身的公共靜態只讀字段。使用 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;
}
}
}
2.14 靜態字段
以下規則概述靜態字段的命名指南:
(1) 使用名詞、名詞短語或者名詞的縮寫命名靜態字段。
(2) 使用 Pascal 大小寫。
(3) 對靜態字段名稱使用匈牙利語表示法前綴。
(4) 建議盡可能使用靜態屬性而不是公共靜態字段。
2.15 集合
集合是一組組合在一起的類似的類型化對象,如哈希表、查詢、堆棧、字典和列表,集合的命名
建議用復數。
第3章表達式和基本語句
3.1 運算符的優先級
C#語言的運算符有數十個,運算符的優先級與結合律如表3-1所示。注意一元運算符 + - * 的優先級高於對應的二元運算符。
優先級
運算符
結合律
從
高
到
低
排
列
( ) [ ] -> .
從左至右
! ~ ++ -- (類型) sizeof
+ - * &
從右至左
* / %
從左至右
+ -
從左至右
<< >>
從左至右
< <= > >=
從左至右
== !=
從左至右
&
從左至右
^
從左至右
|
從左至右
&&
從左至右
||
從右至左
?:
從右至左
= += -= *= /= %= &= ^=
|= <<= >>=
從左至右
表3-1 運算符的優先級與結合律
??如果代碼行中的運算符比較多,用括號確定表達式的操作順序,避免使用默認的優先級。
為了防止產生歧義並提高可讀性,應當用括號確定表達式的操作順序。例如:
word = (high << 8) | low
if ((a | b) && (a & c))
3.2 復合表達式
如 a = b = c = 0這樣的表達式稱為復合表達式。允許復合表達式存在的理由是:(1)書寫簡潔;(2)可以提高編譯效率。但要防止濫用復合表達式。
??(1)不要編寫太復雜的復合表達式。
例如:
i = a >= b && c < d && c + f <= g + h ; // 復合表達式過於復雜
??(2)不要有多用途的復合表達式。
例如:
d = (a = b + c) + r ;
該表達式既求a值又求d值。應該拆分為兩個獨立的語句:
a = b + c;
d = a + r;
??(3)不要把程序中的復合表達式與"真正的數學表達式"混淆。
例如:
if (a < b < c) // a < b < c是數學表達式而不是程序表達式
並不表示
if ((a<b) && (b<c))
而是成了令人費解的
if ( (a<b)<c )
3.3 if 語句
if語句是c# 語言中最簡單、最常用的語句,然而很多程序員用隱含錯誤的方式寫if語句。本節以"與零值比較"為例,展開討論。
3.3.1 布爾變量與零值比較
?? 不可將布爾變量直接與TRUE、FALSE或者1、0進行比較。
根據布爾類型的語義,零值為"假"(記為FALSE),任何非零值都是"真"(記為TRUE)。TRUE的值究竟是什麼並沒有統一的標准。例如 c#將TRUE定義為1,而Visual Basic.net則將TRUE定義為-1。
假設布爾變量名字為flag,它與零值比較的標准if語句如下:
if (flag) // 表示flag為真
if (!flag) // 表示flag為假
其它的用法都屬於不良風格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
3.3.2 整型變量與零值比較
??應當將整型變量用"=="或"!="直接與0比較。
假設整型變量的名字為value,它與零值比較的標准if語句如下:
if (value == 0)
if (value != 0)
不可模仿布爾變量的風格而寫成
if (value) // 會讓人誤解 value是布爾變量
if (!value)
3.3.3 浮點變量與零值比較
??不可將浮點變量用"=="或"!="與任何數字比較。
千萬要留意,無論是float還是double類型的變量,都有精度限制。所以一定要避免將浮點變量用"=="或"!="與數字比較,應該設法轉化成">="或"<="形式。
假設浮點變量的名字為x,應當將
if (x == 0.0) // 隱含錯誤的比較
轉化為
if ((x>=-EPSINON) && (x<=EPSINON))
其中EPSINON是允許的誤差(即精度)。
3.4 循環語句的效率
C# 循環語句中,for語句使用頻率最高,while語句其次,do語句很少用。提高循環體效率的基本辦法是降低循環體的復雜性。
??(1)在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放在最外層,以減少CPU跨切循環層的次數。例如示例3-4(b)的效率比示例3-4(a)的高。
for (row=0; row<100; row++)
{
for ( col=0; col<5; col++ )
{
sum = sum + a[row][col];
}
}
for (col=0; col<5; col++ )
{
for (row=0; row<100; row++)
{
sum = sum + a[row][col];
}
}
示例3-4(a) 低效率:長循環在最外層 示例3-4(b) 高效率:長循環在最內層
??(2) 如果循環體內存在邏輯判斷,並且循環次數很大,宜將邏輯判斷移到循環體的外面。示例3-4(c)的程序比示例3-4(d)多執行了N-1次邏輯判斷。並且由於前者老要進行邏輯判斷,打斷了循環"流水線"作業,使得編譯器不能對循環進行優化處理,降低了效率。如果N非常大,最好采用示例3-4(d)的寫法,可以提高效率。如果N非常小,兩者效率差別並不明顯,采用示例3-4(c)的寫法比較好,因為程序更加簡潔。
for (i=0; i<N; i++)
{
if (condition)
DoSomething();
else
DoOtherthing();
}
if (condition)
{
for (i=0; i<N; i++)
DoSomething();
}
else
{
for (i=0; i<N; i++)
DoOtherthing();
}
表3-4(c) 效率低但程序簡潔 表3-4(d) 效率高但程序不簡潔
3.5 for 語句的循環控制變量
??(1)不可在for 循環體內修改循環變量,防止for 循環失去控制。
??(2)建議for語句的循環控制變量的取值采用"半開半閉區間"寫法。
示例3-5(a)中的x值屬於半開半閉區間"0 =< x < N",起點到終點的間隔為N,循環次數為N。
示例3-5(b)中的x值屬於閉區間"0 =< x <= N-1",起點到終點的間隔為N-1,循環次數為N。
相比之下,示例3-5(a)的寫法更加直觀,盡管兩者的功能是相同的。
for (int x=0; x<N; x++)
{
…
}
for (int x=0; x<=N-1; x++)
{
…
}
示例3-5(a) 循環變量屬於半開半閉區間 示例3-5(b) 循環變量屬於閉區間
3.6 switch語句
switch是多分支選擇語句,而if語句只有兩個分支可供選擇。雖然可以用嵌套的if語句來實現多分支選擇,但那樣的程序冗長難讀。這是switch語句存在的理由。
switch語句的基本格式是:
switch (variable)
{
case value1 : …
break;
case value2 : …
break;
…
default : …
break;
}
??(1)每個case語句的結尾不要忘了加break,否則將導致多個分支重疊(除非有意使多個分支重疊)。
??(2)不要忘記最後那個default分支。即使程序真的不需要default處理,也應該保留語句 default : break; 這樣做並非多此一舉,而是為了防止別人誤以為你忘了default處理。
第4章 Asp.net設計規范
本界面設計規范適用於Asp.net開發的所有頁面。
5.1 頁眉、頁腳和樣式表
??在主窗口中顯示的所有頁面應該包含相同的頁眉文件、頁腳文件和樣式表
??在單獨窗口中顯示的頁面應該包含和主窗口頁面一致的樣式表
??頁面元素的樣式應該在單獨的樣式表中定義,而非直接在頁面中定義各種屬性
5.2頁面標題
??在單獨窗體中呈現的頁面應該定義<title>元素,title必須能夠表達界面的功能
5.3 窗口大小和位置
??彈出的新窗口應在屏幕上處於居中位置,如top=200,left=300
??頁面元素的寬度應盡量使用百分比而避免直接使用像素值,應當保證頁面在800x600滿屏的窗口中顯示時不用橫向移動滾動條
5.4超鏈接
??鏈接到系統內部頁面的超鏈接使用相對路徑
5.5按鈕
??含義相同的按鈕名稱應保持一致,如"確定"、"取消"、"重置"、 "搜索"、"高級搜索"、"新建"、"刪除"、"更改"等
??多於一個的按鈕並排擺放時順序(左右/上下)應保持一致,如"確定"應該在"取消"的左邊
5.6處理結果
??每次處理都應該有相應的處理結果頁面或提示信息,不管該處理是成功還是失敗
??相同處理結果的用語應保持一致,如避免同時使用"失敗"和"沒有成功"這樣意義相同的詞語
5.7 操作確認
??當用戶在進行一些諸如刪除,查封,導入,導出等會對系統造成影響的操作的時候,系統必須用確認框或者確認頁面來提醒用戶,並且讓用戶進行確認。
??任何一個操作頁面,都必須提供給用戶取消操作,並且返回的功能。
5.8 數據驗證
??各個功能頁面,系統都必須進行嚴格的數據驗證,包括長度,類型,是否合法等等
??在asp.net中所有的數據驗證都使用validator控件在客戶端實現。
5.9控件使用
在asp.net中,dot net framework提供了WebControls和HtmlControls兩種控件,但是兩種控件有本質的區別,WebControls是服務器端的控件,服務器在執行的時候需要保留相應控件的狀態等信息,HtmlControls是和Html相關的控件,使用原則如下
??所有需要服務器端進行事件響應的使用WebControl
??無需服務器端相響應的比如超連接,圖片等等盡量使用HtmlControls這樣可以提高效率,減少服務器的負擔,減少網絡傳輸的數據量。
5.10 視圖狀態
Asp.net中每個頁面對象在輸出html結束之後,頁面對象將會被垃圾回收線程給回收掉,為了保存頁面中各個WebControls的狀態,系統會自動將各個WebControl裡面的數據,狀態等信息保存在ViewState中,這樣就極大地加大了文件的大小,為了減少頁面下載的量,試圖狀態的使用原則如下:
??在頁面中判斷Page.IsPostBack屬性,將少對象初始化的量。
??將一些無需保留數據WebControls的EnableViewState改為false
5.11 異常處理
??在各個模塊的類庫中,如果有異常出現則首先將異常寫到日志文件中,同時將異常拋出
??在頁面上盡可能的將所有從封裝的類中拋出來的異常抓起來,並且給用戶比較友好的提示
??當出現非常嚴重的異常時將頁面重定向到errorpage中。
5.12 HTML頁面中需要注意的地方
??去掉頁面中所有的<font>標簽,因為在html標准4.0的時候這個tag就已經不建議使用了。
??為頁面添加正確的DOCTYPE,DOCTYPE是document type的簡寫。主要用來說明你用的XHTML或者HTML是什麼版本。
??設定一個命名空間,一個namespace是收集元素類型和屬性名字的一個詳細的DTD,namespace聲明允許你通過一個在線地址指向來識別你的namespace。
??聲明編碼語言(<meta http-equiv="Content-Type" content="text/html; charset=GB2312" />)。
??用小寫字母寫所有的標簽。
??為圖片添加alt屬性。
??給所有的屬性添加引號
??關閉所有的標簽,及時是<br>也應該寫成<br />。
??所有和顯示顯示相關的控制用css來控制。
??給每一個表格或者表單賦予一個唯一的ID。
5.13 數據庫訪問
??在頁面文件中不要出現任何訪問數據庫的代碼
??訪問數據庫的方式,推薦方式2
??方式1,通過字符串拼接來生成一個完整的SQL語句,如下
SqlConnection objDbConn = new SqlConnection("鏈接字符串");
String strSql = "select * from TUSER_USERINFO where UserID=" + strUserID;
SqlCommand objCommand = new Command(strSql,objDbConn);
SqlDataReader objReader = objCommand.ExecuteReader();
缺陷:SQL Injection漏洞
??方式2,通過參數來實現
SqlConnection objDbConn = new SqlConnection("鏈接字符串");
String strSql = "select * from TUSER_USERINFO where UserID=@UserID";
SqlCommand objCommand = new Command(strSql,objDbConn);
objCommand.Paramters.Add("@UserID",strUserID);
SqlDataReader objReader = objCommand.ExecuteReader();
系統將調用Ms SQLServer2000中的sp_executesql存儲過程來實現,能夠避免漏洞
第5章 javascript編寫規范
6.1 在什麼地方插入 JavaScript
一種方法,JavaScript 出現在 HTML 的head 部分,使用標記<script>…</script>。
另外一種插入 JavaScript 的方法,是把 JavaScript 代碼寫到另一個文件當中(此文件通常應該用".js"作擴展名),然後用格式為"<script src="javascript.js"></script>"的標記把它嵌入到文檔中。注意,一定要用"</script>"標記。
6.2 JavaScript 中的變量
變量的命名有以下要求:只包含字母、數字和/或下劃線;要以字母開頭;不能太長不能與 JavaScript 保留字(Key Words,Reserved Words,數量繁多,不能一一列出;凡是可以用來做 JavaScript 命令的字都是保留字)重復。而且,變量是區分大小寫的,例如,variable 和Variable 是兩個不同的變量。不僅如此,大部分命令和"對象"(請參閱"對象化編程"章)都是區分大小寫的。
提示給變量命名,最好避免用單個字母"a""b""c"等,而改用能清楚表達該變量在程序中的作用的詞語。這樣,不僅別人能更容易的了解你的程序,而且你在以後要修改程序的時候,也很快會記得該變量的作用。變量名一般用小寫,如果是由多個單詞組成的,那麼第一個單詞用小寫,其他單詞的第一個字母用大寫。例如:myVariable 和 myAnotherVariable。這樣做僅僅是為了美觀和易讀,因為 JavaScript 一些命令(以後將用更具體的方法闡述"命令"一詞)都是用這種方法命名的:indexOf;charAt 等等。
變量的賦值一個變量聲明後,可以在任何時候對其賦值。賦值的語法是:
<變量> = <表達式>;
其中"="叫"賦值符",它的作用是把右邊的值賦給左邊的變量。下一節將討論到表達式。
JavaScript常數有下列幾個:
null 一個特殊的空值。當變量未定義,或者定義之後沒有對其進行任何賦值操作,它的值就是"null"。企圖返回一個不存在的對象時也會出現null值。
NaN "Not a Number"。出現這個數值比較少見,以至於我們可以不理它。當運算無法返回正確的數值時,就會返回"NaN"值。NaN 值非常特殊,因為它"不是數字",所以任何數跟它都不相等,甚至 NaN 本身也不等於 NaN 。
true 布爾值"真"。用通俗的說法,"對"。
false 布爾值"假"。用通俗的說法,"錯"。
6.3語句
6.3.1 注釋
JavaScript 注釋有兩種:單行注釋和多行注釋。單行注釋用雙反斜槓"//"表示。當一行代碼有"//",那麼,"//"後面的部分將被忽略。而多行注釋是用"/*"和"*/"括起來的一行到多行文字。程序執行到"/*"處,將忽略以後的所有文字,直到出現"*/"為止
6.3.2 if 語句
if ( <條件> ) <語句1> [ else <語句2> ];本語句有點象條件表達式"?:":當<條件>為真時執行<語句1>,否則,如果 else 部分存在的話,就執行<語句2>。與"?:"不同的是,if 只是一條語句,不會返回數值。<條件>是布爾值,必須用小括號括起來;<語句1>和<語句2>都只能是一個語句,欲使用多條語句,請用語句塊。
if (a == 1)
if (b == 0) alert(a+b);
else
alert(a-b);
if (a == 1)
{
if (b == 0) alert(a+b);
} else {
alert(a-b);
}
示例風格不良的對齊 示例風格良好的對齊
6.3.3 循環體
for (<變量>=<初始值>; <循環條件>; <變量累加方法>)<語句>;
提示適當的使用 for 循環,能使 HTML 文檔中大量的有規律重復的部分簡化,也就是用 for 循環重復寫一些 HTML 代碼,達到提高網頁下載速度的目的。不過請在 Netscape 中重復進行嚴格測試,保證通過了才好把網頁傳上去。作者曾試過多次因為用 for 循環向文檔重復寫 HTML 代碼而導致 Netscape"猝死"。IE 中絕對沒有這種事情發生,如果你的網也是只給 IE 看的,用多多的 for 也沒問題。
6.3.4 switch 語句
如果要把某些數據分類,例如,要把學生的成績按優、良、中、差分類。我們可能會用 if 語句,但使用太多的 if 語句的話,程序看起來有點亂。switch 語句就是解決這種問題的最好方法。
switch (e)
{
case r1: (注意:冒號)
...
[break;]
case r2:
...
[break;]
...
[default:
...]
}
ADO.NET命名規范
數據類型
數據類型簡寫
標准命名舉例
Connection
con
conNorthwind
Command
cmd
cmdReturnProducts
Parameter
parm
parmProductID
DataAdapter
dad
dadProducts
DataReader
dtr
dtrProducts
DataSet
dst
dstNorthWind
DataTable
dtbl
dtblProduct
DataRow
drow
drowRow98
DataColumn
dcol
dcolProductID
DataRelation
drel
drelMasterDetail
DataView
dvw
dvwFilteredProducts
WinForm Control 命名規范
數據類型
數據類型簡寫
標准命名舉例
Label
lbl
lblMessage
LinkLabel
llbl
llblToday
Button
btn
btnSave
TextBox
txt
txtName
MainMenu
mmnu
mmnuFile
CheckBox
chk
chkStock
RadioButton
rbtn
rbtnSelected
GroupBox
gbx
gbxMain
PictureBox
pic
picImage
Panel
pnl
pnlBody
DataGrid
dgrd
dgrdView
ListBox
lst
lstProducts
CheckedListBox
clst
clstChecked
ComboBox
cbo
cboMenu
ListView
lvw
lvwBrowser
TreeView
tvw
tvwType
TabControl
tctl
tctlSelected
DateTimePicker
dtp
dtpStartDate
HscrollBar
hsb
hsbImage
VscrollBar
vsb
vsbImage
Timer
tmr
tmrCount
ImageList
ilst
ilstImage
ToolBar
tlb
tlbManage
StatusBar
stb
stbFootPrint
OpenFileDialog
odlg
odlgFile
SaveFileDialog
sdlg
sdlgSave
FoldBrowserDialog
fbdlg
fgdlgBrowser
FontDialog
fdlg
fdlgFoot
ColorDialog
cdlg
cdlgColor
PrintDialog
pdlg
pdlgPrint
WebControl 命名規范
數據類型
數據類型簡寫
標准命名舉例
AdRotator
adrt
Example
Button
btn
btnSubmit
Calendar
cal
calMettingDates
CheckBox
chk
chkBlue
CheckBoxList
chkl
chklFavColors
CompareValidator
valc
valcValidAge
CustomValidator
valx
valxDBCheck
DataGrid
dgrd
dgrdTitles
DataList
dlst
dlstTitles
DropDownList
drop
dropCountries
HyperLink
lnk
lnkDetails
Image
img
imgAuntBetty
ImageButton
ibtn
ibtnSubmit
Label
lbl
lblResults
LinkButton
lbtn
lbtnSubmit
ListBox
lst
lstCountries
Panel
pnl
pnlForm2
PlaceHolder
plh
plhFormContents
RadioButton
rad
radFemale
RadioButtonList
radl
radlGender
RangeValidator
valg
valgAge
RegularExpression
vale
valeEmail_Validator
Repeater
rpt
rptQueryResults
RequiredFieldValidator
valr
valrFirstName
Table
tbl
tblCountryCodes
TableCell
tblc
tblcGermany
TableRow
tblr
tblrCountry
TextBox
txt
txtFirstName
ValidationSummary
vals
valsFormErrors
XML
xmlc
xmlcTransformResults
變量
變量的作用域及前綴
前綴
說明
舉例
P
全局變量
pstrName
St
靜態變量
ststrName
M
模塊或者窗體的局部變量
MstrName
A
數組
AintCount[]
變量數據類型的前綴
C#數據類型
類庫數據類型
標准命名舉例
Sbyte
System.sbyte
sbte
Short
System.Int16
sht
Int
System.Int32
int
Long
System.Int64
lng
Byte
System.Byte
bte
Ushot
System.Uint16
usht
Uint
System.Uint32
uint
Ulong
System.Uint64
ulng
Float
System.Single
flt
Double
System.Double
dbl
Decimal
System.Decimal
dcl
Bool
System.Boolean
bol
Char
System.Char
chr
Object
System.Object
obj
String
System.String
str
System.DateTime
dte
IntPtr
System.Intpre
intptr
常量定義
常量=作用域+ c+數據類型+變量名
類對象定義
類實例=作用域+cls+變量名
類對象=C+名稱
結構對象定義
結構對象實例=作用域+struc+變量名
結構對象=S+名稱
命名空間定義
以層為前綴進行命名
接口定義
以大寫I為前綴
窗體的命名規則
窗體名=frm+窗體名(名詞+動詞)
注意:保存的文件明和窗體名相同。
枚舉定義規則
以Enum為前綴
事件命名規則
事件控制器要帶有EventHandler後綴
使用sender和e命名兩個參數
事件參數類要帶有EventArgs後綴
考慮使用動詞命名事件
對於有"之前"或"之後"概念的事件,要使用現在時或過去時命名