1. はじめに
想像してみて、君は人気カフェのバリスタだよ。お客さんが来て、5つの好きなドリンクの中から1つを言う。君は哲学的な議論なんてせず、メニューをサッと見て反応する:「カプチーノ?もちろん!はい、カプチーノどうぞ!」。もし全部の選択肢をifで1つずつチェックしてたら、君のコードはランチタイム後のカップの山みたいにゴチャゴチャで使いにくくなるよね。
switch文は、変数の値をスマートにチェックして、結果によって違うアクションを実行できるんだ。使えるデータ型は決まってる(それは後で説明するね)、でもユーザーメニューや簡単なコマンド、ステータス判定には最高のツールだよ。
2. C#のクラシックなswitchの構文
最小限のフローチャートはこんな感じ:
switch (Hyōgen) {
case Kachi1:
// アクション
break;
case Kachi2:
// アクション
break;
...
default:
// デフォルトのアクション
break;
}
例1:クラシックなメニュー
Console.WriteLine("ドリンクを選んでね: 1 - コーヒー, 2 - お茶, 3 - ココア");
string input = Console.ReadLine();
int choice = int.Parse(input);
switch (choice)
{
case 1:
Console.WriteLine("コーヒーを選びました。ナイスチョイス!");
break;
case 2:
Console.WriteLine("お茶もいいね。");
break;
case 3:
Console.WriteLine("ココアはくつろぎ派におすすめ!");
break;
default:
Console.WriteLine("メニューにないドリンクだよ。");
break;
}
- switchブロックはchoiceがcaseの値と等しいかチェックするよ。
- 各caseの後には必ずbreak;を書くこと!書かないと次のcaseにも進んじゃう(後で説明するね)。
- defaultブロックはelseみたいなもの。どのcaseにも当てはまらなかった時に実行されるよ。
switchの中身はどう動く? — ステップバイステップ
- まず、switchのカッコ内の式(この例だとchoice)が評価される。
- プログラムはそれを各caseの値と順番に比べる。
- 一致したら、そのブロックの命令が実行される。その後breakに出会ったら、switchブロックから抜ける。
- どのcaseにも一致しなかったら、defaultブロック(あれば)が実行される。
ビジュアルフロー
| 変数の値 | case 1 | case 2 | case 3 | default |
|---|---|---|---|---|
| 1 | + | |||
| 2 | + | |||
| 3 | + | |||
| その他 | + |
「+」はそのブロックが実行されるって意味だよ
3. クラシックなswitchで使える型は?
クラシックな構文(つまり"Pattern Matching"や新しい機能はナシ!)だと、switchで使えるのは:
- シンプルな整数型(int, byte, char, long, short, sbyte, ushort, uint, ulong)
- 文字列(string)
- 列挙型(enum)
- 文字(char)
例2:文字列で切り替え
Console.WriteLine("コマンドを選んでね: start, stop, pause");
string command = Console.ReadLine();
switch (command)
{
case "start":
Console.WriteLine("プログラムを起動したよ!");
break;
case "stop":
Console.WriteLine("プログラムを停止したよ。");
break;
case "pause":
Console.WriteLine("プログラムは一時停止中。");
break;
default:
Console.WriteLine("知らないコマンドだよ。");
break;
}
4. breakが必要な理由と、忘れたらどうなる?
初心者が一番やりがちなバグは、caseの中でbreak;を忘れること。もし書き忘れたらどうなるか、見てみよう。
例3:次のブロックに落ちる(fall-through)
int day = 2;
switch (day)
{
case 1:
Console.WriteLine("月曜日");
break;
case 2:
Console.WriteLine("火曜日");
case 3:
Console.WriteLine("水曜日");
break;
default:
Console.WriteLine("不明な日");
break;
}
どうなる?
- 入力はday = 2。
- まず"火曜日"が実行される。
- breakがないから、そのままcase 3に進んで"水曜日"も実行される。
- そこでbreak;に出会って終了。
画面にはこう出る:
火曜日
水曜日
これ、よくあるミスだよ!
- 1つだけアクションしたいなら、各caseにbreak;を必ず書こう。
- (たまに)複数のcaseで同じロジックを実行したいなら、caseを「くっつける」(下で説明)こともできるよ。
5. case値のグループ化
複数の値で同じアクションをしたい時、同じコードを何度も書くのは無駄だよね?
例4:複数caseで同じ反応
char grade = 'B';
switch (grade)
{
case 'A':
case 'B':
case 'C':
Console.WriteLine("合格!");
break;
case 'D':
case 'E':
Console.WriteLine("まだ伸びしろあるね。");
break;
default:
Console.WriteLine("無効な評価だよ。");
break;
}
どうなってる?
- gradeが'A'、'B'、'C'なら、最初のブロック:"合格!"が実行される。
- 'D'か'E'なら2番目のブロック。
- それ以外はdefault。
6. クラシックswitchでできること・できないこと
できること:
- caseでリテラル(定数)を使う、例:case 1:、case 'A':、case "stop":。
- enum(列挙型)で比較できる。
- defaultは省略できるけど、普通はあった方が便利。
できないこと:
- caseで変数は使えない(定数だけOK)。
- 範囲で比較はできない(case >= 5:、case x > 10:はダメ!)。
- double、floatなどの実数値は使えない。整数、string、char、enumだけ。
- 1つのcaseでカンマ区切りの複数値はダメ(case 1, 2:はNG。caseを連続で書こう)。
7. 特徴とよくあるミス
実際のプロジェクトでは、switchはメニュー、ステータス処理、コマンド、エラーコードなど色んな場面で使われる。でも、どんなツールにもクセがあるよ。
よくあるミス:
- breakの書き忘れ(さっき説明したやつ)。
- switch式の型が間違ってる(例えばdoubleを使おうとする)。
- 文字列の大文字小文字が合ってない(case "Start":は"start"と一致しない)— 文字列は大文字小文字を区別して比較されるよ!
- 未処理の値(defaultを忘れて、ユーザーが変な値を入れた時)。
ネストしたswitchの罠
こういうコードもたまに見るけど、たいてい読みづらい。もしswitchの中にさらにswitchを書いてるなら、コードを別メソッドに分けたり、OOP/enum/配列を使うタイミングかも。
GO TO FULL VERSION