C# switch文・switch式の使い方完全ガイド|基本構文からパターンマッチングまで

はじめに

C#で条件分岐を書くときによく使われる構文のひとつがswitchです。csharp switchについて調べている方の多くは、「if文との違いがわからない」「switch文とswitch式の使い分けを知りたい」「パターンマッチングの書き方が難しい」と感じているのではないでしょうか。

C#のswitchは、古くからある基本的な条件分岐の構文ですが、近年のC#ではswitch式パターンマッチングが強化され、より短く、読みやすく、保守しやすいコードを書けるようになっています。

この記事では、C#のswitch文・switch式の基本構文から、casedefaultbreakwhen句、型パターン、プロパティパターン、タプルパターン、リレーショナルパターンまで、実践的なコード例を交えながらわかりやすく解説します。

1. C#のswitchとは?条件分岐で使う基本機能

1-1. switch文の役割と使いどころ

C#のswitchは、ある値に応じて処理を分岐させるための構文です。

たとえば、ユーザーが選択したメニュー番号、ステータスコード、曜日、会員ランク、処理種別など、ひとつの値を基準に複数の分岐を行いたい場合に使います。

C#
int menu = 2;

switch (menu)
{
case 1:
Console.WriteLine("新規作成");
break;
case 2:
Console.WriteLine("編集");
break;
case 3:
Console.WriteLine("削除");
break;
default:
Console.WriteLine("不明なメニューです");
break;
}

このように、switchを使うと「値が1ならこの処理、2ならこの処理、3ならこの処理」という分岐を見通しよく書けます。

1-2. if文との違い

if文は、条件式を自由に書けるのが特徴です。

C#
if (score >= 90)
{
Console.WriteLine("A");
}
else if (score >= 80)
{
Console.WriteLine("B");
}
else
{
Console.WriteLine("C");
}

一方、switch文は、基本的にはひとつの対象値に対して複数の候補を比較する場合に向いています。

C#
switch (status)
{
case "open":
Console.WriteLine("開始");
break;
case "closed":
Console.WriteLine("終了");
break;
default:
Console.WriteLine("不明");
break;
}

単純に「同じ値を何度も比較する」ような場合は、if文よりもswitch文のほうが読みやすくなることが多いです。

ただし、複雑な条件を組み合わせる場合や、分岐条件がそれぞれ大きく異なる場合は、if文のほうが自然な場合もあります。

1-3. switch文で扱える値の種類

C#のswitchでは、数値、文字、文字列、enum、bool、null、オブジェクトなど、さまざまな値を扱えます。

代表的な例は次のとおりです。

C#
int number = 1;
string command = "start";
DayOfWeek day = DayOfWeek.Monday;
object value = "C#";

C#の古いswitch文では、主に整数型、文字列、enumなどがよく使われていました。現在のC#ではパターンマッチングにより、型やプロパティ、範囲などを使った柔軟な分岐も可能です。

1-4. C#におけるswitch文とswitch式の違い

C#には大きく分けて、switch文switch式があります。

switch文は、処理を実行するための構文です。

C#
switch (status)
{
case 1:
Console.WriteLine("処理中");
break;
case 2:
Console.WriteLine("完了");
break;
}

一方、switch式は、条件に応じて値を返すための構文です。

C#
string message = status switch
{
1 => "処理中",
2 => "完了",
_ => "不明"
};

処理を複数行で書きたい場合はswitch文、値をシンプルに返したい場合はswitch式が向いています。

2. C# switch文の基本構文と使い方

2-1. switch文の基本構文

C#のswitch文は、次のような構文で書きます。

C#
switch (対象の値)
{
case 値1:
// 値1に一致したときの処理
break;

case 値2:
// 値2に一致したときの処理
break;

default:
// どのcaseにも一致しなかったときの処理
break;
}

switchの丸括弧の中に分岐対象となる値を書き、caseごとに一致した場合の処理を書きます。

2-2. case句の書き方

case句には、対象値と比較する値を書きます。

C#
int level = 2;

switch (level)
{
case 1:
Console.WriteLine("初級");
break;
case 2:
Console.WriteLine("中級");
break;
case 3:
Console.WriteLine("上級");
break;
}

この場合、level2なので、中級と表示されます。

2-3. break文の役割

breakは、switch文の処理を終了するために使います。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
break;
}

C#では、処理のあるcaseから次のcaseへそのまま流れるフォールスルーは基本的に許可されていません。そのため、各caseの最後にはbreakreturnthrowなど、処理の流れを明確に終わらせる文が必要です。

2-4. default句の使い方

default句は、どのcaseにも一致しなかった場合に実行されます。

C#
string command = "unknown";

switch (command)
{
case "start":
Console.WriteLine("開始します");
break;
case "stop":
Console.WriteLine("停止します");
break;
default:
Console.WriteLine("不明なコマンドです");
break;
}

想定外の値に備えるため、defaultはできるだけ書いておくと安全です。

2-5. 複数のcaseで同じ処理を実行する方法

複数のcaseで同じ処理を実行したい場合は、caseを連続して書きます。

C#
int month = 1;

switch (month)
{
case 12:
case 1:
case 2:
Console.WriteLine("冬です");
break;

case 3:
case 4:
case 5:
Console.WriteLine("春です");
break;

default:
Console.WriteLine("その他の季節です");
break;
}

C#では、空のcaseを連続させて、最後のcaseでまとめて処理を書くことができます。

2-6. switch文の実装例

次は、ユーザー権限に応じて処理を分岐する例です。

C#
string role = "admin";

switch (role)
{
case "admin":
Console.WriteLine("管理者メニューを表示します");
break;

case "user":
Console.WriteLine("一般ユーザーメニューを表示します");
break;

case "guest":
Console.WriteLine("ゲストメニューを表示します");
break;

default:
Console.WriteLine("権限が不明です");
break;
}

このように、値の種類ごとに処理を整理したいときにswitch文は便利です。

3. switch文でよく使うパターン

3-1. 数値を条件に分岐する

数値を使った分岐は、switch文の基本的な使い方です。

C#
int statusCode = 200;

switch (statusCode)
{
case 200:
Console.WriteLine("成功");
break;
case 400:
Console.WriteLine("不正なリクエスト");
break;
case 404:
Console.WriteLine("見つかりません");
break;
case 500:
Console.WriteLine("サーバーエラー");
break;
default:
Console.WriteLine("不明なステータスコード");
break;
}

ステータスコードやメニュー番号のように、決まった数値を判定する場合に向いています。

3-2. 文字列を条件に分岐する

C#のswitch文では文字列も扱えます。

C#
string command = "save";

switch (command)
{
case "save":
Console.WriteLine("保存します");
break;
case "load":
Console.WriteLine("読み込みます");
break;
case "exit":
Console.WriteLine("終了します");
break;
default:
Console.WriteLine("不明なコマンドです");
break;
}

コマンド名、カテゴリ名、入力文字列などを判定する場合に便利です。

ただし、文字列の大文字・小文字は区別されます。必要に応じて、事前にToLower()ToUpper()で正規化するとよいでしょう。

C#
string command = input.ToLower();

switch (command)
{
case "start":
Console.WriteLine("開始します");
break;
}

3-3. enumを条件に分岐する

enumとswitch文は非常に相性がよい組み合わせです。

C#
enum OrderStatus
{
Pending,
Shipped,
Delivered,
Canceled
}

OrderStatus status = OrderStatus.Shipped;

switch (status)
{
case OrderStatus.Pending:
Console.WriteLine("注文受付中");
break;
case OrderStatus.Shipped:
Console.WriteLine("発送済み");
break;
case OrderStatus.Delivered:
Console.WriteLine("配達完了");
break;
case OrderStatus.Canceled:
Console.WriteLine("キャンセル済み");
break;
default:
Console.WriteLine("不明な状態");
break;
}

enumを使うと、文字列や数値を直接扱うよりも意味が明確になり、タイプミスも防ぎやすくなります。

3-4. nullを条件に分岐する

switch文ではnullも判定できます。

C#
string? name = null;

switch (name)
{
case null:
Console.WriteLine("名前が入力されていません");
break;
case "":
Console.WriteLine("空文字です");
break;
default:
Console.WriteLine($"こんにちは、{name}さん");
break;
}

nullと空文字は別の値です。入力値を扱う場合は、それぞれの違いを意識して判定しましょう。

3-5. caseで範囲判定を行う方法

C#のパターンマッチングを使うと、caseで範囲判定ができます。

C#
int score = 85;

switch (score)
{
case >= 90:
Console.WriteLine("A");
break;
case >= 80:
Console.WriteLine("B");
break;
case >= 70:
Console.WriteLine("C");
break;
case >= 60:
Console.WriteLine("D");
break;
default:
Console.WriteLine("F");
break;
}

この例では、score85なのでBが表示されます。

また、when句を使って範囲を指定することもできます。

C#
switch (score)
{
case int n when n >= 80 && n < 90:
Console.WriteLine("B");
break;
}

4. C# switch式の基本構文と使い方

4-1. switch式とは

switch式は、条件に応じて値を返すための構文です。

switch文が「処理を分岐する」のに対し、switch式は「分岐結果として値を返す」ことに特化しています。

C#
string result = status switch
{
1 => "処理中",
2 => "完了",
_ => "不明"
};

値を代入したり、メソッドの戻り値として返したりする場面で便利です。

4-2. switch式の基本構文

switch式は、次のように書きます。

C#
var result = 対象の値 switch
{
パターン1 => 値1,
パターン2 => 値2,
_ => デフォルト値
};

switch文と異なり、casebreakは使いません。各分岐は=>で結果を返します。

4-3. アロー構文の書き方

switch式では、=>を使って「この条件ならこの値を返す」と表現します。

C#
int rank = 1;

string rankName = rank switch
{
1 => "ゴールド",
2 => "シルバー",
3 => "ブロンズ",
_ => "未設定"
};

=>の左側に条件、右側に返す値を書きます。

4-4. discardパターン「_」の使い方

_はdiscardパターンと呼ばれ、「それ以外すべて」を表します。

C#
string message = code switch
{
200 => "OK",
404 => "Not Found",
500 => "Server Error",
_ => "Unknown"
};

switch文のdefaultに近い役割を持ちます。想定外の値を安全に処理するため、switch式では_を用意しておくことが多いです。

4-5. switch式で値を返す実装例

次は、点数に応じて評価を返す例です。

C#
int score = 92;

string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
>= 60 => "D",
_ => "F"
};

Console.WriteLine(grade);

switch式を使うと、if-elseを何行も書かずに、シンプルに値を決定できます。

4-6. switch文からswitch式へ書き換える方法

まず、switch文で書いた例を見てみましょう。

C#
string message;

switch (status)
{
case 1:
message = "受付中";
break;
case 2:
message = "処理中";
break;
case 3:
message = "完了";
break;
default:
message = "不明";
break;
}

これをswitch式に書き換えると、次のようになります。

C#
string message = status switch
{
1 => "受付中",
2 => "処理中",
3 => "完了",
_ => "不明"
};

変数に値を代入するだけのswitch文は、switch式に置き換えるとかなり簡潔になります。

5. switch文・switch式のパターンマッチング

5-1. パターンマッチングとは

パターンマッチングとは、値そのものだけでなく、型、プロパティ、範囲、構造などを条件として判定できる機能です。

従来のswitchでは、主に「値が一致するか」を判定していました。パターンマッチングを使うと、「型がstringなら」「プロパティが特定の値なら」「数値が一定範囲なら」といった柔軟な条件分岐が可能になります。

5-2. 型パターンの使い方

型パターンは、オブジェクトの型に応じて分岐する方法です。

C#
object value = "Hello";

switch (value)
{
case int number:
Console.WriteLine($"整数です: {number}");
break;

case string text:
Console.WriteLine($"文字列です: {text}");
break;

case bool flag:
Console.WriteLine($"真偽値です: {flag}");
break;

case null:
Console.WriteLine("nullです");
break;

default:
Console.WriteLine("その他の型です");
break;
}

case string text:のように書くと、型チェックと変数への代入を同時に行えます。

5-3. プロパティパターンの使い方

プロパティパターンは、オブジェクトのプロパティの値を条件に分岐する方法です。

C#
class User
{
public string Name { get; set; } = "";
public int Age { get; set; }
public bool IsMember { get; set; }
}

User user = new User { Name = "田中", Age = 20, IsMember = true };

string message = user switch
{
{ IsMember: true, Age: >= 18 } => "成人会員です",
{ IsMember: true } => "会員です",
{ Age: < 18 } => "未成年です",
_ => "一般ユーザーです"
};

オブジェクトの状態に応じて分岐したい場合に、プロパティパターンは非常に便利です。

5-4. タプルパターンの使い方

タプルパターンは、複数の値の組み合わせで分岐する方法です。

C#
string GetPosition(int x, int y)
{
return (x, y) switch
{
(0, 0) => "原点",
(0, _) => "Y軸上",
(_, 0) => "X軸上",
(> 0, > 0) => "第1象限",
(< 0, > 0) => "第2象限",
(< 0, < 0) => "第3象限",
(> 0, < 0) => "第4象限"
};
}

複数の条件を組み合わせる場合でも、タプルパターンを使うと読みやすく整理できます。

5-5. リレーショナルパターンの使い方

リレーショナルパターンは、<<=>>=を使って値の範囲を判定する方法です。

C#
int temperature = 32;

string message = temperature switch
{
>= 35 => "猛暑日です",
>= 30 => "真夏日です",
>= 25 => "夏日です",
< 0 => "氷点下です",
_ => "通常の気温です"
};

数値の範囲で処理を分けたい場合は、if-elseよりも見通しがよくなることがあります。

5-6. 論理パターン「and」「or」「not」の使い方

C#のパターンマッチングでは、andornotを使って条件を組み合わせられます。

C#
int age = 25;

string category = age switch
{
>= 0 and <= 12 => "子ども",
>= 13 and <= 19 => "ティーン",
>= 20 and <= 64 => "大人",
>= 65 => "シニア",
_ => "不正な年齢"
};

orを使うと、複数の候補をまとめられます。

C#
string dayType = day switch
{
DayOfWeek.Saturday or DayOfWeek.Sunday => "休日",
_ => "平日"
};

notを使うと、特定の条件に一致しない場合を表現できます。

C#
string result = value switch
{
not null => "値があります",
null => "nullです"
};

5-7. when句で条件を追加する方法

when句を使うと、caseに追加条件を付けられます。

C#
object value = 120;

switch (value)
{
case int n when n >= 100:
Console.WriteLine("100以上の整数です");
break;

case int n when n >= 0:
Console.WriteLine("0以上の整数です");
break;

case int n:
Console.WriteLine("負の整数です");
break;

default:
Console.WriteLine("整数ではありません");
break;
}

型パターンや範囲条件と組み合わせることで、より細かい条件分岐ができます。

6. switch文・switch式の実践的なコード例

6-1. 入力値に応じてメッセージを返す

ユーザー入力に応じてメッセージを返す例です。

C#
string input = "help";

string message = input switch
{
"start" => "処理を開始します",
"stop" => "処理を停止します",
"help" => "ヘルプを表示します",
_ => "不明なコマンドです"
};

Console.WriteLine(message);

入力コマンドのように候補が決まっている場合、switch式を使うと簡潔に書けます。

6-2. ステータスコードを判定する

HTTPステータスコードのような数値を判定する例です。

C#
int statusCode = 404;

string result = statusCode switch
{
200 => "成功",
201 => "作成成功",
400 => "リクエストが不正です",
401 => "認証が必要です",
403 => "アクセス権限がありません",
404 => "ページが見つかりません",
>= 500 and <= 599 => "サーバーエラーです",
_ => "不明なステータスコードです"
};

特定の値と範囲判定を組み合わせられる点が、現代的なC# switchの強みです。

6-3. enumで処理を分岐する

注文ステータスに応じて処理を分ける例です。

C#
enum PaymentStatus
{
Unpaid,
Paid,
Refunded,
Failed
}

PaymentStatus status = PaymentStatus.Paid;

switch (status)
{
case PaymentStatus.Unpaid:
Console.WriteLine("未払いです");
break;

case PaymentStatus.Paid:
Console.WriteLine("支払い済みです");
break;

case PaymentStatus.Refunded:
Console.WriteLine("返金済みです");
break;

case PaymentStatus.Failed:
Console.WriteLine("決済に失敗しました");
break;

default:
Console.WriteLine("不明な支払い状態です");
break;
}

enumを使うことで、状態の種類をコード上で明確に表現できます。

6-4. オブジェクトの型ごとに処理を分岐する

オブジェクトの型に応じて処理を変える例です。

C#
object data = 123;

string result = data switch
{
int n => $"整数: {n}",
string s => $"文字列: {s}",
bool b => $"真偽値: {b}",
null => "null",
_ => "その他の型"
};

型判定とキャストを同時にできるため、isやキャストを何度も書く必要がありません。

6-5. 条件に応じて料金やランクを判定する

年齢に応じて料金を判定する例です。

C#
int age = 70;

int price = age switch
{
< 0 => throw new ArgumentException("年齢が不正です"),
<= 6 => 0,
<= 12 => 500,
<= 64 => 1000,
_ => 700
};

Console.WriteLine($"料金は{price}円です");

switch式では、条件に応じて値を返すだけでなく、必要に応じて例外を投げることもできます。

6-6. 複雑なif文をswitch式で簡潔にする

次のようなif-elseがあるとします。

C#
string rank;

if (point >= 1000)
{
rank = "プラチナ";
}
else if (point >= 500)
{
rank = "ゴールド";
}
else if (point >= 100)
{
rank = "シルバー";
}
else
{
rank = "ブロンズ";
}

switch式を使うと、次のように書けます。

C#
string rank = point switch
{
>= 1000 => "プラチナ",
>= 500 => "ゴールド",
>= 100 => "シルバー",
_ => "ブロンズ"
};

値を決定するだけの条件分岐であれば、switch式のほうが読みやすくなることがあります。

7. switch文・switch式の注意点

7-1. breakを書き忘れた場合の挙動

C#のswitch文では、処理のあるcaseの最後にbreakなどを書かないと、コンパイルエラーになります。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
case 2:
Console.WriteLine("2です");
break;
}

このコードは、case 1からcase 2へ処理が流れてしまう可能性があるためエラーになります。

正しくは次のように書きます。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
break;

case 2:
Console.WriteLine("2です");
break;
}

7-2. caseの順番に注意すべきケース

パターンマッチングでは、上から順番に評価され、最初に一致した分岐が実行されます。

C#
int score = 95;

string grade = score switch
{
>= 60 => "合格",
>= 90 => "高得点",
_ => "不合格"
};

この場合、95>= 60に先に一致するため、高得点ではなく合格になります。

正しくは、より限定的な条件を先に書きます。

C#
string grade = score switch
{
>= 90 => "高得点",
>= 60 => "合格",
_ => "不合格"
};

7-3. defaultや「_」を省略した場合のリスク

switch文でdefaultを省略すると、どのcaseにも一致しない場合に何も処理されません。

C#
switch (status)
{
case 1:
Console.WriteLine("開始");
break;
}

この場合、status1以外なら何も起こりません。それが意図した動作なら問題ありませんが、想定外の値を見逃す原因になることがあります。

switch式では、_を省略すると、処理できない値が来たときに例外が発生する可能性があります。

7-4. switch式で網羅性が不足した場合

switch式では、すべての可能性を処理できていない場合、コンパイラが警告を出すことがあります。

C#
string result = status switch
{
1 => "開始",
2 => "終了"
};

この例では、status1でも2でもない場合の結果がありません。

安全に書くには、_を追加します。

C#
string result = status switch
{
1 => "開始",
2 => "終了",
_ => "不明"
};

enumを扱う場合も、将来enumの値が追加される可能性を考慮して、_や例外処理を検討するとよいでしょう。

7-5. 可読性が下がるswitchの書き方

switchは便利ですが、条件を詰め込みすぎると可読性が下がります。

C#
string result = user switch
{
{ Age: >= 20, IsMember: true, Name.Length: > 0 } => "成人会員",
{ Age: >= 20, IsMember: false, Name.Length: > 0 } => "成人非会員",
_ => "その他"
};

条件が複雑になりすぎる場合は、判定ロジックをメソッドに切り出したほうが読みやすくなります。

C#
if (IsAdultMember(user))
{
Console.WriteLine("成人会員");
}

switchを使えば必ず読みやすくなるわけではありません。条件の複雑さに応じて、if文やメソッド分割も検討しましょう。

7-6. バージョンによって使える構文が異なる点

C#のswitchは、バージョンによって使える機能が異なります。

たとえば、switch式はC# 8.0以降で使える構文です。リレーショナルパターンや論理パターンはC# 9.0以降で利用できます。

C#
int score = 80;

string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
_ => "C"
};

古いプロジェクトでこのような構文が使えない場合は、言語バージョンやプロジェクト設定を確認しましょう。

8. switch文・switch式の使い分け

8-1. switch文が向いているケース

switch文は、分岐ごとに複数行の処理を行う場合に向いています。

C#
switch (command)
{
case "save":
SaveFile();
Log("保存しました");
break;

case "load":
LoadFile();
Log("読み込みました");
break;

default:
ShowError();
break;
}

メソッド呼び出し、ログ出力、状態変更など、処理の流れを分岐させたい場合はswitch文がわかりやすいです。

8-2. switch式が向いているケース

switch式は、条件に応じて値を返す場合に向いています。

C#
string label = status switch
{
0 => "未処理",
1 => "処理中",
2 => "完了",
_ => "不明"
};

変数への代入、戻り値の決定、表示ラベルの変換などに適しています。

C#
string GetStatusLabel(int status) => status switch
{
0 => "未処理",
1 => "処理中",
2 => "完了",
_ => "不明"
};

メソッド全体を短く書けるため、単純な変換処理では非常に便利です。

8-3. if文を使うべきケース

次のような場合は、switchよりもif文のほうが向いています。

C#
if (user != null && user.IsActive && user.LastLoginDate >= limitDate)
{
Console.WriteLine("有効なユーザーです");
}

複数の異なる条件を組み合わせる場合や、条件式自体に意味がある場合は、if文のほうが自然です。

また、条件の流れを上から順に説明したい場合も、if文のほうが読みやすいことがあります。

8-4. enumとの組み合わせで使うべき理由

enumとswitchを組み合わせると、状態や種類ごとの処理を明確に書けます。

C#
enum NotificationType
{
Email,
Sms,
Push
}

void Send(NotificationType type)
{
switch (type)
{
case NotificationType.Email:
SendEmail();
break;
case NotificationType.Sms:
SendSms();
break;
case NotificationType.Push:
SendPush();
break;
default:
throw new ArgumentOutOfRangeException(nameof(type));
}
}

文字列で"email""sms"のように書くよりも、enumを使ったほうが安全で保守しやすくなります。

8-5. 可読性と保守性を高める選び方

switch文、switch式、if文の選び方は、次のように考えるとわかりやすいです。

値ごとに処理を分けたいならswitch文、値を返したいならswitch式、自由な条件式を書きたいならif文が向いています。

また、分岐が多すぎる場合は、switchで無理に処理するのではなく、クラス設計や辞書、ポリモーフィズムを検討することも大切です。

C#
var messages = new Dictionary<int, string>
{
[1] = "開始",
[2] = "処理中",
[3] = "完了"
};

string message = messages.TryGetValue(status, out var value)
? value
: "不明";

単純な対応表であれば、switchよりもDictionaryのほうが適している場合もあります。

9. C# switchに関するよくあるエラーと対処法

9-1. 「Control cannot fall through from one case label」エラー

このエラーは、caseの処理が次のcaseへ流れてしまう可能性がある場合に発生します。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
case 2:
Console.WriteLine("2です");
break;
}

対処法は、breakreturnthrowなどを追加して処理の流れを明確に終わらせることです。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
break;

case 2:
Console.WriteLine("2です");
break;
}

9-2. 「A switch expression does not handle all possible values」エラー

switch式で、すべての値を処理できない場合に警告やエラーとして扱われることがあります。

C#
string result = value switch
{
1 => "One",
2 => "Two"
};

この場合、value3などだった場合に対応できません。

対処法は、_を追加してデフォルトの分岐を用意することです。

C#
string result = value switch
{
1 => "One",
2 => "Two",
_ => "Other"
};

想定外の値を許可したくない場合は、例外を投げる書き方もあります。

C#
string result = value switch
{
1 => "One",
2 => "Two",
_ => throw new ArgumentOutOfRangeException(nameof(value))
};

9-3. 型が一致しない場合のエラー

switchで比較する値とcaseの値の型が合わないと、コンパイルエラーになる場合があります。

C#
int value = 1;

switch (value)
{
case "1":
Console.WriteLine("文字列の1");
break;
}

この例では、valueintなのに、caseでは文字列"1"を比較しているため不正です。

正しくは、型を合わせます。

C#
switch (value)
{
case 1:
Console.WriteLine("数値の1");
break;
}

文字列として比較したい場合は、対象値を文字列に変換してからswitchします。

C#
switch (value.ToString())
{
case "1":
Console.WriteLine("文字列の1");
break;
}

9-4. null判定で発生しやすいエラー

nullの可能性がある値をswitchで扱う場合、nullの分岐を忘れると意図しない動作になることがあります。

C#
string? name = null;

string message = name switch
{
"" => "空文字です",
_ => $"こんにちは、{name}さん"
};

この場合、nullでも_に一致するため、こんにちは、さんのような不自然な結果になる可能性があります。

正しくは、nullを明示的に扱います。

C#
string message = name switch
{
null => "名前が未設定です",
"" => "空文字です",
_ => $"こんにちは、{name}さん"
};

nullと空文字を区別するか、同じ扱いにするかは、仕様に合わせて決めましょう。

9-5. when句の条件が意図通りに動かない場合

when句は、まずパターンに一致したあとで追加条件が評価されます。

C#
object value = "hello";

switch (value)
{
case string s when s.Length >= 10:
Console.WriteLine("長い文字列です");
break;

case string s:
Console.WriteLine("短い文字列です");
break;
}

この例では、valueが文字列で、かつ長さが10以上の場合に最初のcaseが実行されます。長さが10未満の場合は、次のcase string sに進みます。

条件の順番を間違えると、意図した分岐に到達しないことがあります。

C#
switch (value)
{
case string s:
Console.WriteLine("文字列です");
break;

case string s when s.Length >= 10:
Console.WriteLine("長い文字列です");
break;
}

このように書くと、長い文字列であっても先にcase string sに一致してしまいます。より具体的な条件を先に書くことが重要です。

10. C# switchのよくある質問

10-1. C#のswitch文で文字列は使える?

はい、C#のswitch文では文字列を使えます。

C#
string command = "start";

switch (command)
{
case "start":
Console.WriteLine("開始");
break;
case "stop":
Console.WriteLine("停止");
break;
}

コマンド、カテゴリ、種別などを文字列で判定したい場合に利用できます。ただし、大文字・小文字は区別されるため注意が必要です。

10-2. C#のswitch文で範囲指定はできる?

はい、現在のC#ではリレーショナルパターンを使って範囲指定ができます。

C#
int score = 75;

string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
_ => "D"
};

switch文でも同様に書けます。

C#
switch (score)
{
case >= 90:
Console.WriteLine("A");
break;
case >= 80:
Console.WriteLine("B");
break;
default:
Console.WriteLine("C");
break;
}

古いC#では、when句を使って範囲判定を書く方法がよく使われます。

10-3. switch文で複数条件を指定できる?

はい、複数のcaseをまとめたり、orパターンを使ったりできます。

C#
switch (day)
{
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
Console.WriteLine("休日");
break;

default:
Console.WriteLine("平日");
break;
}

switch式では、orを使うと簡潔です。

C#
string dayType = day switch
{
DayOfWeek.Saturday or DayOfWeek.Sunday => "休日",
_ => "平日"
};

10-4. switch式と三項演算子はどちらを使うべき?

条件がひとつだけなら三項演算子でも十分です。

C#
string result = age >= 20 ? "成人" : "未成年";

一方、分岐が3つ以上ある場合や、複数の値を比較する場合はswitch式のほうが読みやすくなります。

C#
string result = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
_ => "D"
};

三項演算子を入れ子にすると可読性が下がりやすいため、複数分岐ではswitch式を検討しましょう。

10-5. switch文はif文より高速?

switch文がif文より必ず高速とは限りません。

条件の内容、分岐数、コンパイラの最適化、実行環境によって変わります。単純な数値分岐ではswitchが効率よく最適化される場合がありますが、実務では速度よりも可読性や保守性を優先すべきケースが多いです。

パフォーマンスが本当に重要な箇所では、推測ではなくベンチマークを取って判断しましょう。

10-6. C#のswitchでdefaultは必ず必要?

switch文では、defaultは必須ではありません。

C#
switch (value)
{
case 1:
Console.WriteLine("1です");
break;
}

ただし、想定外の値に対応するためには、defaultを書いておくのが安全です。

switch式でも_は必須ではありませんが、網羅性が不足すると警告が出たり、実行時に例外が発生したりする可能性があります。

C#
string result = value switch
{
1 => "One",
2 => "Two",
_ => "Other"
};

特に外部入力や将来変更される可能性のある値を扱う場合は、default_を用意しておくと安心です。

まとめ

C#のswitchは、条件分岐をわかりやすく整理するための強力な構文です。

基本的なswitch文では、casebreakdefaultを使って、値ごとの処理を分岐できます。数値、文字列、enumなどの決まった値を判定する場面で特に便利です。

一方、C# 8.0以降で使えるswitch式を使うと、条件に応じて値を返す処理を短く書けます。変数への代入やメソッドの戻り値を決める処理では、switch文よりもswitch式のほうが読みやすくなることがあります。

また、C#のパターンマッチングを活用すれば、型パターン、プロパティパターン、タプルパターン、リレーショナルパターン、論理パターン、when句などを使って、より柔軟な条件分岐が可能です。

ただし、switchを使えば常に良いコードになるわけではありません。分岐ごとに処理を実行したいならswitch文、値を返したいならswitch式、複雑な条件式を扱いたいならif文というように、目的に応じて使い分けることが大切です。

csharp switchを正しく理解して使いこなせば、条件分岐のコードをより簡潔で読みやすく、保守しやすい形に改善できます。