Switch文

switch文とは、プログラミング言語において、ある式の値に応じて多分岐を行なう文である。最適化の仕方によって多少変わることはあるが、場合によってはテーブルジャンプなどにより、条件判断を繰り返すif文より効率的に実行される。__TOC__

1. 文法
-----

1.1. C言語
--------

構文は以下の通り。 switch  { case 値1: 文 文 ……… break; case 値2: 文 文 ……… break; default: 文 } 上記の「case」ラベルはいくつでも記述することができる。caseラベルの「値」はコンパイル時に決まる整定数式  である必要がある。

この文は次のような手順で実行される。

制御式を評価し、整数値を得る。
その整数値がどれかのcaseで指定された値であるなら、そのcaseに引き続く文に飛ぶ。
どのcaseでも指定されていなければ、defaultに引き続く文に飛ぶ。
もしdefaultが記述されていなければ、何も実行せずにswitch文を抜ける。

1.1.1. フォールスルー
--------------

ここで注意しなければならないのが、caseはラベルに過ぎず、そのcaseより前からの実行から、そこでswitch文を抜けさせる働きはない点である。このルールはフォールスルー  と言い、制御の流れが合流する動作をさせたい場合に便利であるが、一方でbreak文の書き忘れによるバグ、ループを抜けるbreakと取り違える誤読によるバグなど、バグの温床として問題視されてきた。

そのためlintでは、意図的にフォールスルーしていることを示す/* FALLTHROUGH */などのコメントが記述されていない限り警告を出す。また、Cに類似した構文を採用した言語でも、C#のように対策した言語仕様にされていることがある。

上記の例は、if文を羅列することで同様の動作を実現することができる。なおif文では比較対象の「値」が整定数式である必要がない点においてswitch文よりも柔軟である。 _tmp_ = 制御式; if  { 文 } else if  { 文 }

………

else { 文 }<WtXmlEndTag />

defaultは最後に記述される場合が多いが、必ずしも最後である必要はない。

switchによる分岐は以下のようにdo-while文と組み合わせることも可能である。 switch  { default: do { printf; count++; case 0: printf; count++; case 1: printf; count++; case 2: printf; count++; } while ; } 例えばDuff's deviceではそのような使われ方をしている。

1.2. C#
-------

C#でのswitch文はC言語と似たような見た目であるが、フォールスルーについての挙動は異なる。

switch  { case 0: case 1: // 式が0か1の時に実行 System.Console.WriteLine; return 1;

case 2: System.Console.WriteLine; goto case 3: // case 3も実行

case 3: System.Console.WriteLine; break;

default: System.Console.WriteLine; break; // ここのbreakも省略不可 }<WtXmlEndTag />

C#では、caseラベルは文に付属する扱いとなるが、1つの文に複数のcaseラベルを付けることができる。また、C言語のようなフォールスルーは禁止されており、次のcaseラベル付きの文、あるいはswitchブロックの末端に、通常の制御フローで到達してはならない。すなわち、breakでswitchを抜ける、returnで関数ごと抜ける、例外を投げる、無限ループしてそれ以上進まない、goto caseするなどの書き方が必要となる。goto caseにより、C言語ではフォールスルーを使って書くことができた、制御の合流を書くことができる。

CやC++では、switch文の制御式には整数型の式、またcaseラベルには整定数式しか使用できないのに対し、C#ではそれぞれ文字列型および文字列リテラルも使用できる。また、整数型あるいは整数型に準ずる値型のnull許容型System.Nullableも使用することができる。

C# 7.0以降では型switchを使用できる。 // C# 7.0以降 switch  { case int num when num < 0: Console.WriteLine; break; case string str when str.StartsWith: Console.WriteLine; break; case string str: Console.WriteLine; break; default: Console.WriteLine; break; }

1.3. Go
-------

Goでは、caseに複数の値を指定できる。次のcaseの直前にfallthrough文を置くとフォールスルーになる。

1.4. PHP
--------

PHPでは、C#と同様、文字列にも、switch文が適用できる。 switch  { case "ABC": 文A; break; case "XYZ": 文B; break; case "123": 文C; break; default: 文D; break; } PHPのswitch文においては、比較が===演算子ではなく==演算子で行われる。そのため、曖昧一致に起因し、開発者が予期しない動作となる場合がある。

1.5. BASIC
----------

構造化されたBASICでは、Select Caseステートメントが存在することが多い。このステートメントでは、文字列または整数を対象にできる。 Select Case str Case "ABC" 文A Case "XYZ" 文B Case "123" 文C Case Else 文D End Select

Select Case age Case Is < 20 文A Case 20 To 29 文B Case 30,50,70 'Caseに複数の値を指定することができる 文C Case Else 文D End Select

Cなどと違い、各Caseはラベルではなく、Selectステートメントはフォールスルーでない。

1.6. Perl
---------

Perlでは、perl-5.8以降からuse Switchとした上でswitch case文が使えるようになった。それ以前のバージョンのperlに関しては、Perl付属文章perlsynドキュメントのBasic BLOCKs and Switch Statementsの節に書式の例が書かれている。

1.7. Ruby
---------

Rubyでは、case式により同様の多分岐ができる。フォールスルーはない。ラベルとして置いたものと条件値は===演算子で比較されるため、これをオーバーロードすることでクラスに応じた一致判定を行うことができる。Ruby自体のクラスライブラリ内でも、正規表現の一致判定、範囲オブジェクトでの範囲内かどうかの判定、オブジェクトがあるクラスに属するかの判定など、各種の定義がなされている。

1.8. Mediawiki
--------------

Mediawiki系のTemplateにおいては、ParserFunctionsを用いて多分岐をおこなうことができる。一対一の分岐処理の他、複数の値に対して同一の処理を定義する一種のフォールスルーも実現できる。しかし、CやC#といった言語でのreturn文やbreak文が無い。そのため処理の途中でSwitch文を抜けるにはif等の条件文で処理を囲み、実行させないよう制御する必要がある。

詳細については、Help:条件文#switchの項を参照の事。

1.9. Excel,Libre Office Calcの場合
-------------------------------------------

CHOOSE関数の拡張としてSWITCH関数が利用できる。 SWITCH



2. 条件式ベースで使う
------------

RubyやSQLでは、switchに相当する文の後の式が必須ではなく、省略した場合はwhenとして書かれた式のうち、最初に真となるところを実行するようになる。PHPやJavaScriptなど、caseの式が定数である必要性がない言語の場合、switchと書くことで同様の動作を実現できる。

3. 注釈
-----

4. 出典
-----

5. 関連項目
-------

if文
制御構造

ru:Оператор ветвления#Переключатель