複数の条件で処理を分けたいとき、C#のswitch文はif文よりも読みやすく整理しやすい選択肢になります。
本記事では、初心者の方に向けてswitch文の基本から「複数条件」を扱う実用的な書き方(caseの並列、when条件、論理パターン)までを、注意点とサンプルコード付きで丁寧に解説します。
C#のswitch文の基本と複数条件の考え方(初心者向け)
switchステートメントの書き方とcase/defaultの役割
switch文は、対象となる式の値に応じて分岐します。
各分岐はcase
ラベルで記述し、どのcase
にも当てはまらない場合のフォールバックとしてdefault
を用意します。
using System;
class Program
{
static void Main()
{
int code = 2;
switch (code)
{
case 1:
Console.WriteLine("コード1の処理です。");
break;
case 2:
Console.WriteLine("コード2の処理です。");
break;
default:
Console.WriteLine("その他の処理です。");
break;
}
}
}
コード2の処理です。
default
は任意ですが、想定外の入力に対する安全策として基本的に用意しておくと安心です。
breakとfall-through、goto caseの使い方
C#では「暗黙のフォールスルー(次のcaseへ自動で処理が流れる)」は許可されていません。各caseの末尾にbreak;
(またはreturn;
やthrow;
など)を記述して分岐を終了します。
複数のcaseを同じ処理にしたい場合は、空のcaseラベルを「積み重ね」てから共通の本体へ入ります(これがC#流の明示的なフォールスルー)。
switch (Console.ReadKey(intercept: true).Key)
{
case ConsoleKey.Y:
case ConsoleKey.Enter:
Console.WriteLine("Yes!");
break;
case ConsoleKey.N:
Console.WriteLine("No!");
break;
default:
Console.WriteLine("Unknown!");
break;
}
意図的に別のcase
へジャンプする場合はgoto case
やgoto default
を使います。
int month = 2;
switch (month)
{
case 2:
Console.WriteLine("2月です。");
goto case 1; // 1月のルーチンへ合流
case 1:
Console.WriteLine("期首処理を実行。");
break;
default:
Console.WriteLine("通常処理。");
break;
}
複数条件の書き方パターン(caseの並列・when条件・論理パターン)
同一処理に複数のcaseをまとめる(値の列挙で複数条件を分岐)
同じ処理にしたい具体的な値が複数あるなら、複数のcase
を連続させて1つの本体にまとめます。
読みやすく、重複コードも避けられます。
char c = 'a';
switch (c)
{
case 'a':
case 'i':
case 'u':
case 'e':
case 'o':
Console.WriteLine("母音です。");
break;
default:
Console.WriteLine("子音です。");
break;
}
when条件で複合条件をガードする(case + when の使い方)
case
に対してwhen
を付けると、値に加えた「追加条件」で分岐できます。
複数の入力や状態を組み合わせて判断したいときに便利です。
int age = 30;
bool isMember = true;
switch (age)
{
case int n when n < 0:
Console.WriteLine("年齢が不正です。");
break;
case int n when n < 13:
Console.WriteLine("子ども料金です。");
break;
case int n when n >= 13 && n < 65 && isMember:
Console.WriteLine("大人(会員割引)です。");
break;
case int n when n >= 13 && n < 65:
Console.WriteLine("大人料金です。");
break;
default:
Console.WriteLine("シニア料金です。");
break;
}
or/and と関係演算子で範囲指定(パターンマッチングで複数条件)
C# 9以降では、パターンマッチングのor
(論理和)、and
(論理積)、関係演算子(<
, <=
, >
, >=
)を使って、より宣言的に範囲や複合条件を表現できます。
int score = 85;
switch (score)
{
case >= 90 and <= 100:
Console.WriteLine("A");
break;
case >= 80 and < 90:
Console.WriteLine("B");
break;
case < 0 or > 100:
Console.WriteLine("スコアが範囲外です。");
break;
default:
Console.WriteLine("C/D/Fのいずれかです。");
break;
}
この書き方はwhen
よりも簡潔で、「何点以上かつ何点以下」を読みやすく表現できます。
文字列・enumでの複数条件スイッチ(型と比較の注意点)
文字列のswitchは大文字小文字を区別する比較になります。ケースインシティブにしたい場合は、比較前にToLowerInvariant()
やToUpperInvariant()
で正規化してからスイッチすると安全です。
string command = "Start";
switch (command.ToLowerInvariant())
{
case "start" or "run":
Console.WriteLine("開始します。");
break;
case "stop" or "end":
Console.WriteLine("停止します。");
break;
default:
Console.WriteLine("不明なコマンドです。");
break;
}
enum
は型安全に分岐でき、意図しない値をdefault
で捕捉できます。
DayOfWeek day = DayOfWeek.Sunday;
switch (day)
{
case DayOfWeek.Saturday or DayOfWeek.Sunday:
Console.WriteLine("週末です。");
break;
default:
Console.WriteLine("平日です。");
break;
}
参考(対応バージョンの目安):
パターン | 例 | 必要なC#バージョン |
---|---|---|
複数caseラベル | case 1: case 2: | すべて |
whenガード | case int n when n > 0: | 7.0+ |
関係パターン | case >= 90: | 9.0+ |
and/orパターン | case "a" or "b": / case >= 0 and <= 10: | 9.0+ |
注: プロジェクトのLangVersionが古いとコンパイルできません。
コンパイルできない場合は、必要に応じてcsprojで<LangVersion>latest</LangVersion>
等を設定してください。
サンプルコード:switch文で複数条件を分岐する実例
数値の範囲・複数値をまとめるcaseの例
スコアを成績に変換する典型的なパターンです。
範囲は関係パターンで、異常値はdefault
で扱います。
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var scores = new List<int> { 95, 88, 72, 59, 105, -5 };
foreach (var score in scores)
{
Console.WriteLine($"{score,3} => {ToGrade(score)}");
}
}
static string ToGrade(int score)
{
switch (score)
{
case >= 90 and <= 100:
return "A";
case >= 80 and < 90:
return "B";
case >= 70 and < 80:
return "C";
case >= 60 and < 70:
return "D";
case >= 0 and < 60:
return "F";
default:
return "無効なスコア";
}
}
}
95 => A
88 => B
72 => C
59 => F
105 => 無効なスコア
-5 => 無効なスコア
when条件で入力検証と分岐を行う例
年齢と会員フラグの組み合わせで料金種別を決定します。
外部状態(isMember
)をwhen
でガードしています。
using System;
class Program
{
static void Main()
{
Console.WriteLine(GetPriceType(age: 30, isMember: true)); // 大人(会員割引)
Console.WriteLine(GetPriceType(age: 30, isMember: false)); // 大人
Console.WriteLine(GetPriceType(age: 8, isMember: true)); // 子ども
Console.WriteLine(GetPriceType(age: 70, isMember: false)); // シニア
Console.WriteLine(GetPriceType(age: -1, isMember: false)); // 不正
}
static string GetPriceType(int age, bool isMember)
{
switch (age)
{
case int n when n < 0:
return "年齢が不正です。";
case int n when n < 13:
return "子ども料金です。";
case >= 13 and < 65 when isMember:
return "大人(会員割引)です。";
case >= 13 and < 65:
return "大人料金です。";
default:
return "シニア料金です。";
}
}
}
大人(会員割引)です。
大人料金です。
子ども料金です。
シニア料金です。
年齢が不正です。
文字列・列挙型での複数条件分岐の例
文字列コマンドの同義語をor
でまとめ、曜日はenum
で型安全に分岐します。
using System;
class Program
{
static void Main()
{
Console.WriteLine(HandleCommand("Start")); // 開始
Console.WriteLine(HandleCommand("END")); // 停止
Console.WriteLine(HandleCommand("status")); // 状態
Console.WriteLine(HandleCommand("???")); // 不明
Console.WriteLine(IsWeekend(DayOfWeek.Monday)); // 平日
Console.WriteLine(IsWeekend(DayOfWeek.Saturday)); // 週末
}
static string HandleCommand(string input)
{
switch (input.ToLowerInvariant())
{
case "start" or "run":
return "開始します。";
case "stop" or "end":
return "停止します。";
case "status" or "state":
return "システムの状態を表示します。";
default:
return "不明なコマンドです。";
}
}
static string IsWeekend(DayOfWeek day)
{
switch (day)
{
case DayOfWeek.Saturday or DayOfWeek.Sunday:
return "週末です。";
default:
return "平日です。";
}
}
}
開始します。
停止します。
システムの状態を表示します。
不明なコマンドです。
平日です。
週末です。
よくあるエラー・注意点(初心者がハマりやすいポイント)
breakの付け忘れ、重複したcase、到達不能コード
- C#は暗黙のフォールスルーを許さないため、
break;
の付け忘れはコンパイルエラーや意図せぬreturn/throw
不足の原因になります。各case
の末尾で分岐を確実に終了させます。 - 同じ値を指す
case
を重複して書くとコンパイルエラーになります。まとめたい場合はcaseラベルを積み重ねるか、or
パターンを使います。 - パターンマッチングでは、上にある広い条件が下の詳細な条件を「食い潰す」ことがあります。例えば先に
case >= 0:
を書き、後にcase >= 90:
を書くと後者は到達不能です。広い条件は下に、狭い条件は上に並べるのが原則です。
条件の優先順位とdefaultの置き方(フォールバック設計)
switchは上から順に最初にマッチしたcase
が実行されます。
したがって、
- 狭い条件(特定の値・具体的な範囲)を上に、
- 広い条件(全体をカバーする総称的な範囲や
default
)を下に : 配置します。default
は基本的に最後に置くと読み手がフォールバック先を見つけやすくなります。
switch式との比較と使い分け(簡潔に複数条件を書く)
switchステートメントとの違いと複数条件の表現方法
C# 8以降では「switch式」を使って、式として値を返す宣言的な書き方ができます。
分岐ごとにbreak
が不要で、戻り値の取り扱いが簡潔です。
ステートメント版(前出の成績変換):
static string ToGrade(int score)
{
switch (score)
{
case >= 90 and <= 100: return "A";
case >= 80 and < 90: return "B";
case >= 70 and < 80: return "C";
case >= 60 and < 70: return "D";
case >= 0 and < 60: return "F";
default: return "無効なスコア";
}
}
スイッチ式版(より簡潔):
static string ToGrade(int score) => score switch
{
>= 90 and <= 100 => "A",
>= 80 and < 90 => "B",
>= 70 and < 80 => "C",
>= 60 and < 70 => "D",
>= 0 and < 60 => "F",
_ => "無効なスコア"
};
- 複数条件(
or
/and
、関係パターン)はスイッチ式でも同様に使えます。 - 逐次的な処理や副作用(ログ出力や変数更新など)が多い場合はステートメント版、単に値を選択して返したい場合はスイッチ式が向いています。
まとめ:C#のswitch文で複数条件を安全・簡潔に書くコツ
複数の値を同じ処理にしたい場合は、caseラベルを積み重ねるかor
パターンを使って読みやすく整理します。
追加の条件が必要なときはwhen
でガードし、外部状態や細かい検証を自然に組み込みます。
範囲指定や複合条件にはC# 9以降の関係パターンとand
/or
を使うと宣言的で誤りにくく書けます。
文字列は大文字小文字の扱いに注意し、必要なら正規化してからスイッチします。enumは型安全でおすすめです。
広い条件は下、狭い条件は上。default
は最後のフォールバックとして準備し、予期しない値を確実に捕捉します。
値を返すだけならスイッチ式で簡潔に。副作用を含む処理ならステートメント版が扱いやすいです。
これらの原則を押さえると、ifの連鎖よりも読みやすく保守しやすい分岐が書けます。
まずは小さなコードから、when
やパターンを少しずつ取り入れていくことをおすすめします。