第1章程序的版式
版式雖然不會影響程序的功能,但會影響可讀性。程序的版式追求清晰、美觀,是程序風格的重要構(gòu)成因素。
可以把程序的版式比喻為"書法"。好的"書法"可讓人對程序一目了然,看得興致勃勃。差的程序"書法"如螃蟹爬行,讓人看得索然無味,更令維護者煩惱有加。
1.1 版本和版權(quán)聲明
版本和版權(quán)的聲明寫在文件的開頭,包含內(nèi)容如下:
1、版權(quán)信息
2、摘要
3、當前版本
4、作者
5、修改作者
6、完成日期
7、版本歷史信息
例:
///<copyright> Copyright (c) 2006,有限公司</copyright> ///<copyright> All rights reserved.</copyright> ///<abstract>描述文件的內(nèi)容,實現(xiàn)的功能和算法等內(nèi)容</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> |
版本版權(quán)聲明示例 |
在C#中代碼注釋這樣寫的好處是Visual Stuidio能夠在編譯的時候自動生成xml格式的注釋文檔。
1.2空行
空行起著分隔程序段落的作用??招械皿w(不過多也不過少)將使程序的布局更加清晰??招胁粫速M內(nèi)存,雖然打印含有空行的程序是會多消耗一些紙張,但是值得。所以不要舍不得用空行。
在每個類聲明之后、每個函數(shù)定義結(jié)束之后都要加空行。參見示例1-2(a)在一個函數(shù)體內(nèi),邏揖上密切相關(guān)的語句之間不加空行,其它地方應加空行分隔。參見示例1-2(b )
// 空行 void Function1(…) { … } // 空行 void Function2(…) { … } // 空行 void Function3(…) { … }
| // 空行 while (condition) { statement1; // 空行 if (condition) { statement2; } else { statement3; } // 空行 statement4; } |
示例1-2(a) 函數(shù)之間的空行 示例1-2(b) 函數(shù)內(nèi)部的空行
1.3 代碼行
(1)一行代碼只做一件事情,如只定義一個變量,或只寫一條語句。這樣的代碼容易閱讀,并且方便于寫注釋。
(2)if、for、while、do等語句自占一行,執(zhí)行語句不得緊跟其后。不論執(zhí)行語句有多少都要加{}。這樣可以防止書寫失誤。
示例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 代碼行內(nèi)的空格
(1)關(guān)鍵字之后要留空格。象const、case 等關(guān)鍵字之后至少要留一個空格,否則無法辨析關(guān)鍵字。象if、for、while等關(guān)鍵字之后應留一個空格再跟左括號'(',以突出關(guān)鍵字。
(2)函數(shù)名之后不要留空格,緊跟左括號'(',以與關(guān)鍵字區(qū)別。
(3)'('向后緊跟,')'、','、';'向前緊跟,緊跟處不留空格。
(4)','之后要留空格,如Function(x, y, z)。如果';'不是一行的結(jié)束符號,其后要留空格,如for (initialization; condition; update)。
(5)賦值操作符、比較操作符、算術(shù)操作符、邏輯操作符、位域操作符,如"="、"+=" ">="、"<="、"+"、"*"、"%"、"&&"、"||"、"<<","^"等二元操作符的前后應當加空格。
(6)一元操作符如"!"、"~"、"++"、"--"、"&"(地址運算符)等前后不加空格。
(7)象"[]"、"."、"->"這類操作符前后不加空格。
(8)對于表達式比較長的for語句和if語句,為了緊湊起見可以適當?shù)厝サ粢恍┛崭瘢鏵or (i=0; i<10; i++)和if ((a<=b) && (c<=d))
示例1-4 代碼行內(nèi)的空格
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){ }之內(nèi)的代碼塊在'{'右邊數(shù)格處左對齊。
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 } |
如果出現(xiàn)嵌套的{},則使用縮進對齊,如: { … { … } … } |
|
示例1-5(a) 風格良好的對齊 示例1-5(b) 風格不良的對齊
1.6長行拆分
代碼行最大長度宜控制在70至80個字符以內(nèi)。代碼行不要過長,否則眼睛看不過來,也不便于打印。
長表達式要在低優(yōu)先級操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當?shù)目s進,使排版整齊,語句可讀。
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#語言中,程序塊的注釋常采用"/*…*/",行注釋一般采用"http://…"。注釋通常用于:
(1)版本、版權(quán)聲明;
(2)函數(shù)接口說明;
(3)重要的代碼行或段落提示。
(4) 雖然注釋有助于理解代碼,但注意不可過多地使用注釋。
(5)注釋是對代碼的"提示",而不是文檔。程序中的注釋不可喧賓奪主,注釋太多了會讓人眼花繚亂。注釋的花樣要少。
(6)如果代碼本來就是清楚的,則不必加注釋。否則多此一舉,令人厭煩。例如
i++; // i 加 1,多余的注釋
(7)邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
(8)注釋應當準確、易懂,防止注釋有二義性。錯誤的注釋不但無益反而有害。
(9)盡量避免在注釋中使用縮寫,特別是不常用縮寫。
(10)注釋的位置應與被描述的代碼相鄰,可以放在代碼的上方或右方,不可放在下方。
(11)當代碼比較長,特別是有多重嵌套時,應當在一些段落的結(jié)束處加注釋,便于閱讀。
/* * 函數(shù)介紹: * 輸入?yún)?shù): * 輸出參數(shù): * 返回值 : */ void Function(float x, float y, float z) { … } |
if (…) { … while (…) { … } // end of while … } // end of if |
示例1-7 程序的注釋
第2章命名規(guī)則
所有標識符的命名必須遵循如下三種大小寫規(guī)范進行命名:
風格 | 說明 | 樣例 |
Pascal 大小寫 | 首字母大寫,且后續(xù)單詞的首字母都必須大寫; 本規(guī)則一般用于三個或更多字母的標識 的情況 | BackColor |
Camel 大小寫 | 首字母小寫,且后續(xù)單詞的首字母都必須大寫; 本規(guī)則僅用于函數(shù)參數(shù)和保護實例成員的命名中 | backColor |
大寫格 | 所有字母都必須大寫 本規(guī)則僅用于標識只有兩個或更少字母的情況 | System.IO System.Web.UI |
2.1 大小寫規(guī)則
大寫標識符中的所有字母都大寫。僅對于由兩個或者更少字母組成的標識符使用該約定。例如:
System.IO
System.Web.UI
下表匯總了大寫規(guī)則,并提供了不同類型的標識符的示例。
標識符 | 大小寫 | 示例 |
類 | Pascal | AppDomain |
枚舉類型 | Pascal | ErrorLevel |
枚舉值 | Pascal | FatalError |
事件 | Pascal | ValueChange |
異常類 | Pascal | WebException 注意總是以 Exception 后綴結(jié)尾。 |
只讀的靜態(tài)字段 | Pascal | RedValue |
接口 | Pascal | IDisposable 注意總是以 I 前綴開始。 |
方法 | Pascal | ToString |
命名空間 | Pascal | System.Drawing |
屬性 | Pascal | BackColor |
公共實例字段 | Pascal | RedValue 注意很少使用。屬性優(yōu)于使用公共實例字段。 |
受保護的實例字段 | Camel | redValue 注意很少使用。屬性優(yōu)于使用受保護的實例字段。 |
私有的實例字段 | Camel | redValue |
參數(shù) | Camel | typeName |
方法內(nèi)的變量 | Camel | backColor |
2.2縮寫
為了避免混淆和保證跨語言交互操作,請遵循有關(guān)區(qū)縮寫的使用的下列規(guī)則:
(1) 不要將縮寫或縮略形式用作標識符名稱的組成部分。例如,使用 GetWindow,而不要使用 GetWin。
(2) 不要使用計算機領域中未被普遍接受的縮寫。
(3) 在適當?shù)臅r候,使用眾所周知的縮寫替換冗長的詞組名稱。例如,用 UI 作為 User Interface 縮寫,用 OLAP 作為 On-line Analytical Processing 的縮寫。
(4) 在使用縮寫時,對于超過兩個字符長度的縮寫請使用 Pascal 大小寫或 Camel 大寫。例如,使用 HtmlButton 或HTMLButton。但是,應當大寫僅有兩個字符的縮寫,如,System.IO,而不是 System.Io。
(5) 不要在標識符或參數(shù)名稱中使用縮寫。如果必須使用縮寫,對于由多于兩個字符所組成的縮寫請使用Camel 大小寫,雖然這和單詞的標準縮寫相沖突。
2.3命名空間
(1) 命名命名空間時的一般性規(guī)則是使用公司名稱,后跟技術(shù)名稱和可選的功能與設計,如下所示。
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 是作為類名稱組成部分的整個單詞的第一個字母,這便是適當?shù)摹@?,類名稱 IdentityStore 是適當?shù)?。在適當?shù)牡胤剑褂脧秃蠁卧~命名派生的類。派生類名稱的第二個部分應當是基類的名稱。例如,applicationException 對于從名為 Exception 的類派生的類是適當?shù)拿Q,原因ApplicationException 是一種Exception。請在應用該規(guī)則時進行合理的判斷。例如,Button 對于從 Control 派生的類是適當?shù)拿Q。盡管按鈕是一種控件,但是將 Control 作為類名稱的一部分將使名稱不必要地加長。
public class FileStream
public class Button
public class String
2.5接口
以下規(guī)則概述接口的命名指南:
(1) 用名詞或名詞短語,或者描述行為的形容詞命名接口。例如,接口名稱 IComponent 使用描述性名詞。接口名稱ICustomAttributeProvider 使用名詞短語。名稱 IPersistable 使用形容詞。
(2) 使用 Pascal 大小寫。
(3) 少用縮寫。
(4) 給接口名稱加上字母 I 前綴,以指示該類型為接口。在定義類/接口對(其中類是接口的標準實現(xiàn))時使用相似的名稱。兩個名稱的區(qū)別應該只是接口名稱上有字母 I 前綴。
(5) 不要使用下劃線字符 (_)。
(6) 當類是接口的標準執(zhí)行時,定義這一對類/接口組合就要使用相似的名稱。兩個名稱的不同之處只是接口名前有一個I前綴。
以下是正確命名的接口的示例。
public interface IServiceProvider
public interface IFormatable
以下代碼示例闡釋如何定義 IComponent 接口及其標準實現(xiàn) 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 類繼承。以下規(guī)則概述枚舉的命名指南:
(1) 對于 Enum 類型和值名稱使用 Pascal 大小寫。
(2) 少用縮寫。
(3) 不要在 Enum 類型名稱上使用 Enum 后綴。
(4) 對大多數(shù) Enum 類型使用單數(shù)名稱,但是對作為位域的 Enum 類型使用復數(shù)名稱。
(5) 總是將 FlagsAttribute 添加到位域 Enum 類型。
2.8參數(shù)
以下規(guī)則概述參數(shù)的命名指南:
(1) 使用描述性參數(shù)名稱。參數(shù)名稱應當具有足夠的描述性,以便參數(shù)的名稱及其類型
可用于在大多數(shù)情況下確定它的含義。
(2) 對參數(shù)名稱使用 Camel 大小寫。
(3) 使用描述參數(shù)的含義的名稱,而不要使用描述參數(shù)的類型的名稱。開發(fā)工具將提
供有關(guān)參數(shù)的類型的有意義的信息。因此,通過描述意義,可以更好地使用參
數(shù)的名稱。少用基于類型的參數(shù)名稱,僅在適合使用它們的地方使用它們。
(4) 不要使用保留的參數(shù)。保留的參數(shù)是專用參數(shù),如果需要,可以在未來的版本中公
開它們。相反,如果在類庫的未來版本中需要更多的數(shù)據(jù),請為方法添加新的重載。
(5) 不要給參數(shù)名稱加匈牙利語類型表示法的前綴。
以下是正確命名的參數(shù)的示例。
Type GetType(string typeName)
string Format(string format, args() As object)
2.9方法
以下規(guī)則概述方法的命名指南:
(1) 使用動詞或動詞短語命名方法。
(2) 使用 Pascal 大小寫。
(3) 以下是正確命名的方法的實例。
RemoveAll()
GetCharArray()
Invoke()
2.10 屬性 (property)
以下規(guī)則概述屬性的命名指南:
(1) 使用名詞或名詞短語命名屬性。
(2) 使用 Pascal 大小寫。
(3) 不要使用匈牙利語表示法。
(4) 考慮用與屬性的基礎類型相同的名稱創(chuàng)建屬性。例如,如果聲明名為 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事件
以下規(guī)則概述事件的命名指南:
(1) 對事件處理程序名稱使用 EventHandler 后綴。
(2) 指定兩個名為 sender 和 e 的參數(shù)。sender 參數(shù)表示引發(fā)事件的對象。sender 參數(shù)始終是object 類型的,即使在可以使用更為特定的類型時也如此。與事件相關(guān)聯(lián)的狀態(tài)封裝在名為 e 的事件類的實例中。對 e 參數(shù)類型使用適當而特定的事件類。
(3) 用 EventArgs 后綴命名事件參數(shù)類。
(4) 考慮用動詞命名事件。
(5) 使用動名詞(動詞的"ing"形式)創(chuàng)建表示事件前的概念的事件名稱,用過去式表示事件后。例如,可以取消的 Close 事件應當具有 Closing 事件和 Closed 事件。不要使用BeforeXxx/AfterXxx 命名模式。
(6) 不要在類型的事件聲明上使用前綴或者后綴。例如,使用 Close,而不要使用 OnClose。
(7) 通常情況下,對于可以在派生類中重寫的事件,應在類型上提供一個受保護的方法(稱為OnXxx)。此方法只應具有事件參數(shù)e,因為發(fā)送方總是類型的實例。
以下示例闡釋具有適當名稱和參數(shù)的事件處理程序。
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
以下示例闡釋正確命名的事件參數(shù)類。
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)
以下規(guī)則概述常量的命名指南:
所有單詞大寫,多個單詞之間用 "_" 隔開。如
public const string PAGE_TITLE = "Welcome";
2.13 字段
以下規(guī)則概述字段的命名指南:
(1) private、protected 使用 Camel 大小寫。
(2) public 使用 Pascal 大小寫。
(3) 拼寫出字段名稱中使用的所有單詞。僅在開發(fā)人員一般都能理解時使用縮寫。字段名稱不要使用大寫字母。下面是正確命名的字段的示例。
class SampleClass
{
string url;
string destinationUrl;
}
(4) 不要對字段名使用匈牙利語表示法。好的名稱描述語義,而非類型。
(5) 不要對字段名或靜態(tài)字段名應用前綴。具體說來,不要對字段名稱應用前綴來區(qū)分靜態(tài)和非靜態(tài)字段。例如,應用 g_ 或s_ 前綴是不正確的。
(6)對預定義對象實例使用公共靜態(tài)只讀字段。如果存在對象的預定義實例,則將它們聲明為對象本身的公共靜態(tài)只讀字段。使用 Pascal 大小寫,原因是字段是公共的。下面的代碼示例闡釋公共靜態(tài)只讀字段的正確使用。
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 靜態(tài)字段
以下規(guī)則概述靜態(tài)字段的命名指南:
(1) 使用名詞、名詞短語或者名詞的縮寫命名靜態(tài)字段。
(2) 使用 Pascal 大小寫。
(3) 對靜態(tài)字段名稱使用匈牙利語表示法前綴。
(4) 建議盡可能使用靜態(tài)屬性而不是公共靜態(tài)字段。
2.15 集合
集合是一組組合在一起的類似的類型化對象,如哈希表、查詢、堆棧、字典和列表,集合的命名
建議用復數(shù)。
第3章表達式和基本語句
3.1 運算符的優(yōu)先級
C#語言的運算符有數(shù)十個,運算符的優(yōu)先級與結(jié)合律如表3-1所示。注意一元運算符 + - * 的優(yōu)先級高于對應的二元運算符。
優(yōu)先級 | 運算符 | 結(jié)合律 |
從
高
到
低
排
列 | ( ) [ ] -> . | 從左至右 |
! ~ ++ -- (類型) sizeof + - * & | 從右至左
| |
* / % | 從左至右 | |
+ - | 從左至右 | |
<< >> | 從左至右 | |
< <= > >= | 從左至右 | |
== != | 從左至右 | |
& | 從左至右 | |
^ | 從左至右 | |
| | 從左至右 | |
&& | 從左至右 | |
|| | 從右至左 | |
?: | 從右至左 | |
= += -= *= /= %= &= ^= |= <<= >>= | 從左至右 |
表3-1 運算符的優(yōu)先級與結(jié)合律
??如果代碼行中的運算符比較多,用括號確定表達式的操作順序,避免使用默認的優(yōu)先級。
為了防止產(chǎn)生歧義并提高可讀性,應當用括號確定表達式的操作順序。例如:
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)不要把程序中的復合表達式與"真正的數(shù)學表達式"混淆。
例如:
if (a < b < c) // a < b < c是數(shù)學表達式而不是程序表達式
并不表示
if ((a<b) && (b<c))
而是成了令人費解的
if ( (a<b)<c )
3.3 if 語句
if語句是c# 語言中最簡單、最常用的語句,然而很多程序員用隱含錯誤的方式寫if語句。本節(jié)以"與零值比較"為例,展開討論。
3.3.1 布爾變量與零值比較
?? 不可將布爾變量直接與TRUE、FALSE或者1、0進行比較。
根據(jù)布爾類型的語義,零值為"假"(記為FALSE),任何非零值都是"真"(記為TRUE)。TRUE的值究竟是什么并沒有統(tǒng)一的標準。例如 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 浮點變量與零值比較
??不可將浮點變量用"=="或"!="與任何數(shù)字比較。
千萬要留意,無論是float還是double類型的變量,都有精度限制。所以一定要避免將浮點變量用"=="或"!="與數(shù)字比較,應該設法轉(zhuǎn)化成">="或"<="形式。
假設浮點變量的名字為x,應當將
if (x == 0.0) // 隱含錯誤的比較
轉(zhuǎn)化為
if ((x>=-EPSINON) && (x<=EPSINON))
其中EPSINON是允許的誤差(即精度)。
3.4 循環(huán)語句的效率
C# 循環(huán)語句中,for語句使用頻率最高,while語句其次,do語句很少用。提高循環(huán)體效率的基本辦法是降低循環(huán)體的復雜性。
??(1)在多重循環(huán)中,如果有可能,應當將最長的循環(huán)放在最內(nèi)層,最短的循環(huán)放在最外層,以減少CPU跨切循環(huán)層的次數(shù)。例如示例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) 低效率:長循環(huán)在最外層 示例3-4(b) 高效率:長循環(huán)在最內(nèi)層
??(2) 如果循環(huán)體內(nèi)存在邏輯判斷,并且循環(huán)次數(shù)很大,宜將邏輯判斷移到循環(huán)體的外面。示例3-4(c)的程序比示例3-4(d)多執(zhí)行了N-1次邏輯判斷。并且由于前者老要進行邏輯判斷,打斷了循環(huán)"流水線"作業(yè),使得編譯器不能對循環(huán)進行優(yōu)化處理,降低了效率。如果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 語句的循環(huán)控制變量
??(1)不可在for 循環(huán)體內(nèi)修改循環(huán)變量,防止for 循環(huán)失去控制。
??(2)建議for語句的循環(huán)控制變量的取值采用"半開半閉區(qū)間"寫法。
示例3-5(a)中的x值屬于半開半閉區(qū)間"0 =< x < N",起點到終點的間隔為N,循環(huán)次數(shù)為N。
示例3-5(b)中的x值屬于閉區(qū)間"0 =< x <= N-1",起點到終點的間隔為N-1,循環(huán)次數(shù)為N。
相比之下,示例3-5(a)的寫法更加直觀,盡管兩者的功能是相同的。
for (int x=0; x<N; x++) { … } | for (int x=0; x<=N-1; x++) { … } |
示例3-5(a) 循環(huán)變量屬于半開半閉區(qū)間 示例3-5(b) 循環(huán)變量屬于閉區(qū)間
3.6 switch語句
switch是多分支選擇語句,而if語句只有兩個分支可供選擇。雖然可以用嵌套的if語句來實現(xiàn)多分支選擇,但那樣的程序冗長難讀。這是switch語句存在的理由。
switch語句的基本格式是:
switch (variable)
{
case value1 : …
break;
case value2 : …
break;
…
default : …
break;
}
??(1)每個case語句的結(jié)尾不要忘了加break,否則將導致多個分支重疊(除非有意使多個分支重疊)。
??(2)不要忘記最后那個default分支。即使程序真的不需要default處理,也應該保留語句 default : break; 這樣做并非多此一舉,而是為了防止別人誤以為你忘了default處理。
第4章 asp.net設計規(guī)范
本界面設計規(guī)范適用于Asp.net開發(fā)的所有頁面。
5.1 頁眉、頁腳和樣式表
??在主窗口中顯示的所有頁面應該包含相同的頁眉文件、頁腳文件和樣式表
??在單獨窗口中顯示的頁面應該包含和主窗口頁面一致的樣式表
??頁面元素的樣式應該在單獨的樣式表中定義,而非直接在頁面中定義各種屬性
5.2頁面標題
??在單獨窗體中呈現(xiàn)的頁面應該定義<title>元素,title必須能夠表達界面的功能
5.3 窗口大小和位置
??彈出的新窗口應在屏幕上處于居中位置,如top=200,left=300
??頁面元素的寬度應盡量使用百分比而避免直接使用像素值,應當保證頁面在800x600滿屏的窗口中顯示時不用橫向移動滾動條
5.4超鏈接
??鏈接到系統(tǒng)內(nèi)部頁面的超鏈接使用相對路徑
5.5按鈕
??含義相同的按鈕名稱應保持一致,如"確定"、"取消"、"重置"、 "搜索"、"高級搜索"、"新建"、"刪除"、"更改"等
??多于一個的按鈕并排擺放時順序(左右/上下)應保持一致,如"確定"應該在"取消"的左邊
5.6處理結(jié)果
??每次處理都應該有相應的處理結(jié)果頁面或提示信息,不管該處理是成功還是失敗
??相同處理結(jié)果的用語應保持一致,如避免同時使用"失敗"和"沒有成功"這樣意義相同的詞語
5.7 操作確認
??當用戶在進行一些諸如刪除,查封,導入,導出等會對系統(tǒng)造成影響的操作的時候,系統(tǒng)必須用確認框或者確認頁面來提醒用戶,并且讓用戶進行確認。
??任何一個操作頁面,都必須提供給用戶取消操作,并且返回的功能。
5.8 數(shù)據(jù)驗證
??各個功能頁面,系統(tǒng)都必須進行嚴格的數(shù)據(jù)驗證,包括長度,類型,是否合法等等
??在asp.net中所有的數(shù)據(jù)驗證都使用validator控件在客戶端實現(xiàn)。
5.9控件使用
在asp.net中,dot net framework提供了WebControls和HtmlControls兩種控件,但是兩種控件有本質(zhì)的區(qū)別,WebControls是服務器端的控件,服務器在執(zhí)行的時候需要保留相應控件的狀態(tài)等信息,HtmlControls是和Html相關(guān)的控件,使用原則如下
??所有需要服務器端進行事件響應的使用WebControl
??無需服務器端相響應的比如超連接,圖片等等盡量使用HtmlControls這樣可以提高效率,減少服務器的負擔,減少網(wǎng)絡傳輸?shù)臄?shù)據(jù)量。
5.10 視圖狀態(tài)
Asp.net中每個頁面對象在輸出html結(jié)束之后,頁面對象將會被垃圾回收線程給回收掉,為了保存頁面中各個WebControls的狀態(tài),系統(tǒng)會自動將各個WebControl里面的數(shù)據(jù),狀態(tài)等信息保存在ViewState中,這樣就極大地加大了文件的大小,為了減少頁面下載的量,試圖狀態(tài)的使用原則如下:
??在頁面中判斷Page.IsPostBack屬性,將少對象初始化的量。
??將一些無需保留數(shù)據(jù)WebControls的EnableViewState改為false
5.11 異常處理
??在各個模塊的類庫中,如果有異常出現(xiàn)則首先將異常寫到日志文件中,同時將異常拋出
??在頁面上盡可能的將所有從封裝的類中拋出來的異常抓起來,并且給用戶比較友好的提示
??當出現(xiàn)非常嚴重的異常時將頁面重定向到errorpage中。
5.12 HTML頁面中需要注意的地方
??去掉頁面中所有的<font>標簽,因為在html標準4.0的時候這個tag就已經(jīng)不建議使用了。
??為頁面添加正確的DOCTYPE,DOCTYPE是document type的簡寫。主要用來說明你用的XHTML或者HTML是什么版本。
??設定一個命名空間,一個namespace是收集元素類型和屬性名字的一個詳細的DTD,namespace聲明允許你通過一個在線地址指向來識別你的namespace。
??聲明編碼語言(<meta http-equiv="Content-Type" content="text/html; charset=GB2312" />)。
??用小寫字母寫所有的標簽。
??為圖片添加alt屬性。
??給所有的屬性添加引號
??關(guān)閉所有的標簽,及時是<br>也應該寫成<br />。
??所有和顯示顯示相關(guān)的控制用CSS來控制。
??給每一個表格或者表單賦予一個唯一的ID。
5.13 數(shù)據(jù)庫訪問
??在頁面文件中不要出現(xiàn)任何訪問數(shù)據(jù)庫的代碼
??訪問數(shù)據(jù)庫的方式,推薦方式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,通過參數(shù)來實現(xiàn)
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();
系統(tǒng)將調(diào)用Ms SQLServer2000中的sp_executesql存儲過程來實現(xiàn),能夠避免漏洞
第5章 javascript編寫規(guī)范
6.1 在什么地方插入 Javascript
一種方法,JavaScript 出現(xiàn)在 HTML 的head 部分,使用標記<script>…</script>。
另外一種插入 JavaScript 的方法,是把 JavaScript 代碼寫到另一個文件當中(此文件通常應該用".js"作擴展名),然后用格式為"<script src="javascript.js"></script>"的標記把它嵌入到文檔中。注意,一定要用"</script>"標記。
6.2 JavaScript 中的變量
變量的命名有以下要求:只包含字母、數(shù)字和/或下劃線;要以字母開頭;不能太長不能與 JavaScript 保留字(Key Words,Reserved Words,數(shù)量繁多,不能一一列出;凡是可以用來做 JavaScript 命令的字都是保留字)重復。而且,變量是區(qū)分大小寫的,例如,variable 和Variable 是兩個不同的變量。不僅如此,大部分命令和"對象"(請參閱"對象化編程"章)都是區(qū)分大小寫的。
提示給變量命名,最好避免用單個字母"a""b""c"等,而改用能清楚表達該變量在程序中的作用的詞語。這樣,不僅別人能更容易的了解你的程序,而且你在以后要修改程序的時候,也很快會記得該變量的作用。變量名一般用小寫,如果是由多個單詞組成的,那么第一個單詞用小寫,其他單詞的第一個字母用大寫。例如:myVariable 和 myAnotherVariable。這樣做僅僅是為了美觀和易讀,因為 JavaScript 一些命令(以后將用更具體的方法闡述"命令"一詞)都是用這種方法命名的:indexOf;charAt 等等。
變量的賦值一個變量聲明后,可以在任何時候?qū)ζ滟x值。賦值的語法是:
<變量> = <表達式>;
其中"="叫"賦值符",它的作用是把右邊的值賦給左邊的變量。下一節(jié)將討論到表達式。
JavaScript常數(shù)有下列幾個:
null 一個特殊的空值。當變量未定義,或者定義之后沒有對其進行任何賦值操作,它的值就是"null"。企圖返回一個不存在的對象時也會出現(xiàn)null值。
NaN "Not a Number"。出現(xiàn)這個數(shù)值比較少見,以至于我們可以不理它。當運算無法返回正確的數(shù)值時,就會返回"NaN"值。NaN 值非常特殊,因為它"不是數(shù)字",所以任何數(shù)跟它都不相等,甚至 NaN 本身也不等于 NaN 。
true 布爾值"真"。用通俗的說法,"對"。
false 布爾值"假"。用通俗的說法,"錯"。
6.3語句
6.3.1 注釋
JavaScript 注釋有兩種:單行注釋和多行注釋。單行注釋用雙反斜杠"http://"表示。當一行代碼有"http://",那么,"http://"后面的部分將被忽略。而多行注釋是用"/*"和"*/"括起來的一行到多行文字。程序執(zhí)行到"/*"處,將忽略以后的所有文字,直到出現(xiàn)"*/"為止
6.3.2 if 語句
if ( <條件> ) <語句1> [ else <語句2> ];本語句有點象條件表達式"?:":當<條件>為真時執(zhí)行<語句1>,否則,如果 else 部分存在的話,就執(zhí)行<語句2>。與"?:"不同的是,if 只是一條語句,不會返回數(shù)值。<條件>是布爾值,必須用小括號括起來;<語句1>和<語句2>都只能是一個語句,欲使用多條語句,請用語句塊。
if (a == 1)
| if (a == 1) {
|
示例風格不良的對齊 示例風格良好的對齊
6.3.3 循環(huán)體
for (<變量>=<初始值>; <循環(huán)條件>; <變量累加方法>)<語句>;
提示適當?shù)氖褂?nbsp;for 循環(huán),能使 HTML 文檔中大量的有規(guī)律重復的部分簡化,也就是用 for 循環(huán)重復寫一些 HTML 代碼,達到提高網(wǎng)頁下載速度的目的。不過請在 Netscape 中重復進行嚴格測試,保證通過了才好把網(wǎng)頁傳上去。作者曾試過多次因為用 for 循環(huán)向文檔重復寫 HTML 代碼而導致 Netscape"猝死"。IE 中絕對沒有這種事情發(fā)生,如果你的網(wǎng)也是只給 IE 看的,用多多的 for 也沒問題。
6.3.4 switch 語句
如果要把某些數(shù)據(jù)分類,例如,要把學生的成績按優(yōu)、良、中、差分類。我們可能會用 if 語句,但使用太多的 if 語句的話,程序看起來有點亂。switch 語句就是解決這種問題的最好方法。
switch (e)
{
case r1: (注意:冒號)
...
[break;]
case r2:
...
[break;]
...
[default:
...]
}
ADO.NET命名規(guī)范
WinForm Control 命名規(guī)范
WebControl 命名規(guī)范
變量
變量數(shù)據(jù)類型的前綴
類對象定義 結(jié)構(gòu)對象定義 命名空間定義 接口定義 窗體的命名規(guī)則 枚舉定義規(guī)則 事件命名規(guī)則 |
|
新聞熱點
疑難解答