66

この質問は主にC/C ++を対象としていますが、他の言語も関連していると思います。

if /elseifの代わりにswitch/caseがまだ使用されている理由がわかりません。私にはgotoを使用するのとよく似ており、同じ種類の厄介なコードになりますが、if / else ifを使用すると、はるかに整理された方法で同じ結果を得ることができます。

それでも、私はこれらのブロックをかなり頻繁に見かけます。それらを見つける一般的な場所はメッセージループ(WndProc ...)の近くですが、これらは最も重い大混乱を引き起こす場所の1つです。変数は、適切でない場合でもブロック全体で共有されます(その中で初期化されます)。休憩を落とさないように特に注意する必要があります...

個人的には使わないのですが、何か足りないのかな?

それらはif/elseよりも効率的ですか?彼らは伝統によって引き継がれていますか?

4

15 に答える 15

170

私の最初の投稿とコメントを要約すると、 /ステートメントswitchよりもステートメントの方がいくつかの利点があります。ifelse

  1. よりクリーンなコード。複数の連鎖if/else if ...乱雑に見え、保守が難しいコード -switchよりクリーンな構造を提供します。

  2. パフォーマンス。密度の高いcase値の場合、コンパイラはジャンプ テーブルを生成します。疎 - 二分探索または一連のif/elseの場合、最悪の場合は/switchと同じくらい高速ですが、通常は高速です。一部のコンパイラは同様に/を最適化できますが。ifelseifelse

  3. テストの順序は関係ありません。一連のif/elseテストをスピードアップするには、より可能性の高いケースを最初に置く必要があります。With switch/caseプログラマーはこれについて考える必要はありません。

  4. デフォルトはどこでもかまいません。With if/ elsedefault ケースは最後にある必要があります - last の後else。In switch-defaultプログラマーがより適切と判断した場所であれば、どこにでも置くことができます。

  5. 共通コード。複数のケースで共通のコードを実行する必要がある場合は、省略してもかまいません。実行は「失敗」します。これは/breakでは実現できません。(このような場合には、特別なコメントを配置することをお勧めします。lint はそれを認識し、文句を言いません。このコメントがなければ、忘れるのが一般的なエラーであるため、文句を言います)。ifelse/* FALLTHROUGH */break

すべてのコメント投稿者に感謝します。

于 2009-06-22T17:30:07.463 に答える
31

まあ、1つの理由は明快さです....

スイッチ/ケースがある場合、式は変更できません....つまり

switch (foo[bar][baz]) {
case 'a':
    ...
    break;
case 'b': 
    ...
    break;
}

一方、if/else では、誤って (または意図的に) 書いた場合:

if (foo[bar][baz] == 'a') {
    ....
}
else if (foo[bar][baz+1] == 'b') {
    ....
}

あなたのコードを読んでいる人は、「foo 式は同じはずだったのに」、「なぜ違うのだろう」と疑問に思うでしょう。

于 2009-06-22T17:32:49.287 に答える
17

case/select により柔軟性が増すことに注意してください。

  • 条件は一度評価されます
  • ダフのデバイスのようなものを構築するのに十分な柔軟性があります
  • フォールスルー (ブレークのないケース)

はるかに高速に実行されるだけでなく(ジャンプ/ルックアップテーブルを介して)*歴史的に

于 2009-06-22T17:37:38.517 に答える
10

多くのケースがある場合、switch ステートメントの方がすっきりしているように見えます。

同じ動作が必要な複数の値がある場合にも便利です。単一の実装にフォールスルーする複数の「ケース」ステートメントを使用するだけで、if( this || that || something || .. . )

于 2009-06-22T17:35:37.863 に答える
7

言語にも依存する場合があります。たとえば、一部の言語スイッチは数値型でのみ機能するため、列挙値、数値定数などを操作するときに入力を節約できます...

If (day == DAYOFWEEK_MONDAY) {
    //...
}
else if (day == DAYOFWEEK_TUESDAY) {
    //...
}
//etc...

それとももう少し読みやすい...

switch (day) {
    case DAYOFWEEK_MONDAY :
        //...
    case DAYOFWEEK_TUESDAY :
        //...
    //etc...
}
于 2009-06-22T17:32:58.740 に答える
4

通常、スイッチ/ケースは if/else if/else よりも効率的に最適化されますが、(言語とコンパイラによっては) 単純な if/else if/else ステートメントに変換されることがあります。

個人的には、switch ステートメントを使用すると、一連の if ステートメントよりもコードが読みやすくなると思います。いくつかの簡単なルールに従うことが条件です。if/else if/else の状況でもおそらく従うべきルールですが、それも私の意見です。

それらのルール:

  • switch ブロックに複数の行を設定しないでください。メソッドまたは関数を呼び出して、そこで作業を行います。
  • ブレーク/ケースのフォールスルーを常に確認してください。
  • 例外をバブルアップします。
于 2009-06-22T17:29:23.067 に答える
4

明瞭さ。ここで言ったように、問題のある手がかりelse if

構文で許可されているよりもはるかに制限された方法で ELSE IF が使用される頻度。これは柔軟性の大ハンマーであり、まったく無関係な条件をテストできます。しかし、同じ式を代替値と比較して、CASEのハエをたたくために日常的に使用されています...

これにより、コードの可読性が低下します。構造が条件付きの複雑さの世界を許容するので、読者は CASE を解析するときよりも ELSE IF を解析するときにより多くの可能性を心に留めておく必要があります。

于 2009-06-22T17:40:20.947 に答える
4

実際には、switch ステートメントは、何が起こっているのかをすぐに知る手がかりとなる多かれ少なかれ列挙型の何かに取り組んでいることを意味します。

とはいえ、オブジェクト指向言語の列挙型のスイッチは、おそらくより適切にコーディングできます。また、同じ「列挙型」スタイルの値に対する一連の if/else は、意味を伝えるのに少なくとも同じくらい悪いか、さらに悪いでしょう。

于 2009-06-22T17:46:44.933 に答える
3

スイッチ内のすべてのスコープが同等であるという懸念に対処するために、ケース ロジックをいつでも別の { } ブロックにスローできます。

switch( thing ) {
    case ONETHING: {
        int x; // local to the case!
        ...
        }
        break;
    case ANOTHERTHING: {
        int x; // a different x than the other one
        }
        break;
}

.. 今、私はそれがきれいだと言っているのではありません。あるケースで何かを別のケースから絶対に分離する必要がある場合に、可能なものとしてそれを公開するだけです。

スコープの問題に関するもう1つの考え-関数内にスイッチを1つだけ配置し、他にはあまり配置しないことをお勧めします。このような状況では、変数のスコープはそれほど重要ではありません。これは、通常、関数の特定の呼び出しで実行の 1 つのケースのみを処理するためです。

わかりました、スイッチに関する最後の考え: 関数に 2 つ以上のスイッチが含まれている場合は、おそらくコードをリファクタリングする時期です。関数にネストされたスイッチが含まれている場合、おそらく設計を少し再考する手がかりになります =)

于 2009-06-25T00:18:42.413 に答える
1

switch case は、主にプログラミングで選択するために使用されます。これは、次のような条件文とは関係ありません。

プログラムで選択のみが必要な場合は、if/else ブロックを使用してプログラミングの労力を増やし、プログラムの実行速度を低下させる理由。

于 2010-03-27T09:48:03.577 に答える
0

if/と同じものにコンパイルされることは確かelse ifですが、switch/caseが 2 つまたは 3 つ以上あると読みやすくなりますelse

于 2009-06-22T17:29:10.803 に答える
0

switch ステートメントは速度を最適化できますが、case 値が多数の値に分散している場合は、より多くのメモリを消費する可能性があります。

各値をチェックする必要があるため、if/else は一般的に低速です。

于 2009-06-22T17:32:47.897 に答える
0

Smalltalker は、switch と if-then-else の両方を拒否し、次のように書くかもしれません:-

shortToLongDaysMap := Dictionary new.

shortToLongDaysMap
at: 'Mon'     put:  'Monday';
at: 'Tue'     put:  'Tuesday';
at: 'Wed'     put:  'Wednesday'
etc etc.

longForm := shortToLongDaysMap at: shortForm ifAbsent: [shortForm]

これは些細な例ですが、この手法が多数のケースにどのように対応するかを理解していただければ幸いです。

2 番目の引数 toat:IfAbsent:は、case ステートメントの default 句に似ていることに注意してください。

于 2009-06-22T18:01:16.080 に答える
0

この背後にある主な理由は、保守性と読みやすさです。Switch/case ステートメントと if/else を使用して、コードを読みやすく保守しやすくするのは簡単です。多くの if/else があるため、コードは入れ子のように乱雑になり、維持するのが非常に困難になります。

そして、実行時間も別の理由です。

于 2010-08-03T11:53:03.343 に答える