某些時(shí)候,在嵌套使用if語(yǔ)句時(shí),所有if語(yǔ)句看起來(lái)都非常相似,因?yàn)樗鼈兌荚趯?duì)一個(gè)完全相同的表達(dá)式進(jìn)行求值,惟一的區(qū)別是每個(gè)if語(yǔ)句都將表達(dá)式的結(jié)果與一個(gè)不同的值進(jìn)行比較。例如:
if (day == 0)
dayname = "sunday";
else if (day == 1)
dayname = "monday";
else if (day == 2)
dayname = "tuesday";
else if (day == 3)
...
else
dayname = "unknown";
在這些情況下,通常需要將嵌套的if語(yǔ)句改寫(xiě)為一個(gè)switch語(yǔ)句,使程序更有效、更容易懂。
理解switch語(yǔ)句的語(yǔ)法
switch語(yǔ)句的語(yǔ)法如下(switch,case和default是關(guān)鍵字):
switch ( controllingexpression )
{
case constantexpression :
statements
break;
case constantexpression :
statements
break;
...
default :
statements
break;
}
controllingexpression(控制表達(dá)式)只求值一次。然后,從其constantexpression值等于controllingexpression值的case開(kāi)始,它下方的所有語(yǔ)句都會(huì)一直運(yùn)行,直到遇到一個(gè)break為止。隨后,switch語(yǔ)句將結(jié)束,程序從switch結(jié)束大括號(hào)之后的第一個(gè)語(yǔ)句繼續(xù)執(zhí)行,并忽略其他case。
假如任何一個(gè)constantexpression值都不等于controllingexpression的值,就運(yùn)行可選標(biāo)簽default之下的語(yǔ)句。
注意 假如controllingexpression的值和任何一個(gè)case標(biāo)簽都不匹配,同時(shí)沒(méi)有發(fā)現(xiàn)一個(gè)default標(biāo)簽,程序會(huì)跳過(guò)整個(gè)switch語(yǔ)句,從它的結(jié)束大括號(hào)之后的第一個(gè)語(yǔ)句繼續(xù)執(zhí)行。
例如,前面的嵌套if語(yǔ)句可以改寫(xiě)為以下switch語(yǔ)句:
switch (day)
{
case 0 :
dayname = "sunday";
break;
case 1 :
dayname = "monday";
break;
case 2 :
dayname = "tuesday";
break;
...
default :
dayname = "unknown";
break;
}
遵守switch語(yǔ)句規(guī)則
switch語(yǔ)句非常有用,但在使用時(shí)必須謹(jǐn)慎。所寫(xiě)的任何switch語(yǔ)句都必須遵循以下規(guī)則:
只能針對(duì)基本數(shù)據(jù)類(lèi)型使用switch,這些類(lèi)型包括int和string等待。對(duì)于其他類(lèi)型,則必須使用if語(yǔ)句。
case標(biāo)簽必須是常量表達(dá)式(constantexpression),如42或者"42"。如果需要在運(yùn)行時(shí)計(jì)算case標(biāo)簽的值,必須使用if語(yǔ)句。
case標(biāo)簽必須是惟一性的表達(dá)式;也就是說(shuō),不允許兩個(gè)case具有相同的值。
可以連續(xù)寫(xiě)下一系列case標(biāo)簽(中間不能間插額外的語(yǔ)句),從而指定自己希望在多種情況下都運(yùn)行相同的語(yǔ)句。如果像這樣寫(xiě),那么最后一個(gè)case標(biāo)簽之后的代碼將適用于所有case。然而,假如一個(gè)標(biāo)簽關(guān)聯(lián)了一個(gè)或多個(gè)語(yǔ)句,又沒(méi)有使用break來(lái)跳出,那么執(zhí)行就不能貫穿到后續(xù)的標(biāo)簽,而且編譯器會(huì)報(bào)告一個(gè)錯(cuò)誤。例如:
switch (trumps)
{
case hearts :
case diamonds : // 允許貫穿 — 標(biāo)簽之間無(wú)額外代碼
color = "red"; // 針對(duì)hearts和diamonds這兩種情況都會(huì)執(zhí)行的代碼
break;
case clubs :
color = "black";
case spades : // 出錯(cuò) — 標(biāo)簽之間有額外代碼,而且沒(méi)有使用break來(lái)跳出
color = "black";
break;
}
注意 break語(yǔ)句是用來(lái)阻止貫穿的最常見(jiàn)的方式,但也可以用一個(gè)return語(yǔ)句或者一個(gè)throw語(yǔ)句來(lái)替代它。throw語(yǔ)句的詳情將在以后討論。
不準(zhǔn)貫穿
由于c#存在不準(zhǔn)貫穿(fall through)的規(guī)則,所以可以自由地安排一個(gè)switch語(yǔ)句的各個(gè)區(qū)域,而不至于影響其含義(其中包括default標(biāo)簽,它傳統(tǒng)意義上是最后一個(gè)標(biāo)簽,但并非一定如此)。
c和c++程序員要注意的是,在使用c#編程時(shí),必須為switch語(yǔ)句中的每個(gè)case(包括default case)都提供一個(gè)break語(yǔ)句。這個(gè)要求是一件好事情,c和c++程序員經(jīng)常忘記添加break語(yǔ)句,造成執(zhí)行自動(dòng)貫穿到后續(xù)的標(biāo)簽,并造成很難發(fā)現(xiàn)的bug。
然而,如果你真的喜歡,也可以在c#中模擬c++的貫穿行為,方法是使用一個(gè)goto語(yǔ)句來(lái)轉(zhuǎn)到下一個(gè)case或者default標(biāo)簽。但這種用法是不推薦的,本書(shū)也不打算介紹具體細(xì)節(jié)!
在下面的練習(xí)中,我們準(zhǔn)備完成一個(gè)程序,它將讀取一個(gè)字符串中包含的字符,并將每個(gè)字符都映射成它的xml形式。例如,'<'字符在xml中具有特殊含義(用于構(gòu)成元素),所以要想正確顯示它,就必須轉(zhuǎn)換成"<"。我們打算寫(xiě)一個(gè)switch語(yǔ)句來(lái)測(cè)試字符的值,并將特殊xml字符作為case標(biāo)簽來(lái)使用。
編寫(xiě)switch語(yǔ)句
1. 啟動(dòng)visual studio 2005。
2. 打開(kāi)switchstatement項(xiàng)目,它位于my documents文件夾下的/microsoft press/visual csharp step by step/chapter 4/switchstatement子文件夾中。
3. 選擇“調(diào)試”|“開(kāi)始執(zhí)行(不調(diào)試)”。
visual studio 2005將生成并運(yùn)行應(yīng)用程序。窗體上將出現(xiàn)上下兩個(gè)文本框,中間用一個(gè)copy按鈕分隔。如圖所示。

圖 兩個(gè)文本框用一個(gè)copy按鈕隔開(kāi)
4. 在上方的文本框中輸入以下示例文本:
inrange = (lo <= number) && (number <= hi);
5. 單擊copy。
所有內(nèi)容會(huì)逐字復(fù)制到下方的文本框中,期間不會(huì)對(duì)'<'字符進(jìn)行轉(zhuǎn)換。
6. 關(guān)閉窗體。
7. 在“代碼和文本編輯器”窗口中顯示form1.cs的代碼,找到copyone方法。
copyone方法負(fù)責(zé)將一個(gè)字符從上方的文本框復(fù)制到下方的文本框。目前,copyone方法中包含了一個(gè)switch語(yǔ)句,但其中只提供了一個(gè)default小節(jié)。
在后續(xù)的步驟中,我們將修改這個(gè)switch語(yǔ)句,使它能將xml中的特殊字符轉(zhuǎn)換成xml映射形式。例如,'<'字符將轉(zhuǎn)換成字符串"<"。
8. 在switch語(yǔ)句中,于default標(biāo)簽上方添加以下語(yǔ)句:
case '<' :
target.text += "<";
break;
case '>' :
target.text += ">";
break;
case '&' :
target.text += "&";
break;
case '/"' :
target.text += """;
break;
case '/'' :
target.text += "'";
break;
注意 在最后兩個(gè)case中,反斜杠(/)是一個(gè)轉(zhuǎn)義符,它會(huì)造成后續(xù)的字符(即"和')被視為一個(gè)直接量,而不是被視為字符串或字符常量的定界符。
9. 選擇“調(diào)試”|“開(kāi)始執(zhí)行(不調(diào)試)”。
visual studio 2005將生成并運(yùn)行應(yīng)用程序。
10. 在上方的文本框中輸入以下文本:
inrange = (lo <= number) && (number <= hi);
11. 單擊copy。
所有內(nèi)容會(huì)復(fù)制到下方的文本框中。這一次,每個(gè)字符都會(huì)在switch語(yǔ)句中進(jìn)行xml映射處理。
12. 關(guān)閉窗體。