2017-10-06 156 views
1

Switch語句:我知道他們在做什麼 - 根據慣例,我常常使用它們很多次,當我想根據Enum的值做不同的事情時,但現在它只是打我:爲什麼我們要使用它?它最初的目的是什麼?我的意思是,這樣的:switch語句是什麼?

switch(myVar) { 
    case Foo: 
     doSomething(); 
     break; 
    case Bar: 
     doSomethingElse(); 
     break; 
    default: 
     justAnotherThing(); 
     break; 
} 

具有完全相同的行爲:

if(myVar == Foo) { 
    doSomething() 
}else if(myVar == Bar) { 
    doSomethingElse(); 
}else { 
    justAnotherThing(); 
} 

if的讓你做不平等的比較(><!=),如果你需要它。我可能會發現一個開關更有用的唯一情況是當你不使用內部的break聲明時:但這種情況不會太頻繁,我發現代碼質量很糟糕。

我真的找不到使用switch而非if的任何好處......那麼爲什麼要定義它?

+2

現在做相同的'if-else if'鏈有十個選擇,或二十,你會發現它不是很可讀。另外,編譯器可能能夠將'switch'優化成簡單的跳轉表,而不必評估每個條件直到找到「匹配」。並且請記住,如果沒有「break」,那麼在類C語言中(您似乎將其用作基礎)的情況*會通過*到達下一個「case」。這在if-else if鏈中很難做到。 –

+0

至於閱讀能力,我認爲他們幾乎是平等的 - 只要你保持一致的身份,並且你使用'switch'的情況下使用if-else if',否則if (myVar =='總是佔用相同的空間將使所有可能的值對齊並且易於閱讀 – olivarra1

+0

而在我的問題中,我通過刪除'break'來提及fall-through行爲,但這對可讀性來說很糟糕:所以你有可能會或可能不會跳到下一個案件的案件,以及改變案件的順序都會影響行爲,我只是用這個「把戲」來比較或者比較一個開關,並試圖避免出現其他情況。 – olivarra1

回答

4

某些語言還允許在switch語句中進行不等式比較,例如, Visual Basic中:

Select Case x 
    Case < 5 
    // ... 
    Case 7 
    // ... 
    Case 10 To 15 
    // ... 
    Case Else 
    // ... 
End Select 

基本上,是的,switch往往可以寫成if/else if梯,與switch對一些比較值一個值進行比較的區別,if/else if可以做任何事在每一個分支。但即使如此,在所有的語言中都不是這種情況,例如在PowerShell中switch可以做很多的事情,你通常必須使用if爲:

switch -Regex ($x) { 
    '^\d+$' {'Number'} 
} 

switch ($x) { 
    { $_ is [int] -or $_ is [double] } {'Number'} 
    { $_ is [string] } {'Text'} 
} 

但是,總的來說,switch更容易閱讀比較單一的常見情況價值與一套有限的選擇。此外,它還使編譯器能夠執行某些優化,這些優化在if/else if上難以分析,例如使用二進制搜索來確定正確的大小寫而不是線性搜索,或者甚至使用跳轉表或算術。例如。下面的開關

switch (x) { 
    case 0: 
    // Do something with 0 
    break; 
    case 1: 
    // Do something with 1 
    break; 
    case 2: 
    // Do something with 2 
    break; 
    ... 
} 

可以編譯成

Action[] actions = { 
() => { /* Do something with 0 */ }, 
() => { /* Do something with 1 */ }, 
() => { /* Do something with 2 */ }, 
    ... 
}; 
if (x >=0 && x <= n) { 
    actions[x](); 
} 

等效的簡單和switch侷限在這種情況下的優化編譯器有幫助的,因爲有少得多的分析,以確定哪些整體結構正試圖做到。

還有其他功能(有時可能是可疑的值),如Duff's device,或能夠轉入其他情況(或goto任意其他情況下,例如C#允許)。

您可能還會問爲什麼我們有if語句和循環而不是僅使用goto。是的,與更一般的構造相比,結構化編程構造一個接一個地被嚴格地表現爲劣勢。但它們更具可讀性,使意圖更清晰,並且趨於更安全和更易於維護。

2

switch是一個相當低級的語句,從這個意義上說,case語句中的代碼被編譯成內存中的連續指令塊,只是有條件地跳入內存中(取決於當前所討論的語言,現代高級語言的行爲可能會非常不同)。這也是爲什麼你有失敗的原因,一旦確定了起始地址,只需執行下面的所有指令,除非中斷。

所以最初這是一種非常自然的方式來跳過或進入一個指令塊。許多語言都採用了switch聲明,很多可能是因爲熟悉,但很多也有可能是因爲它確實相當可讀某些情況下,例如:

switch (someComplicatedCalculation($foo, $bar)) { 
    case CONSTANT_A: 
     ... 
    case CONSTANT_B: 
     ... 
    ... 
} 

這是一個非常簡潔的方式來表達這一點,特別是當你也許也取決於跌倒的行爲。

當然,其他語言從未採用switch,例如, Python,並且需要使用if..elif..else來代替。最後,您可以使用任一種語言構造編寫類似的代碼,這取決於您。