C#プログラミングにおいて、特定の条件に基づいて処理を分岐させる「条件分岐」は最も基本的な処理の一つです。
その中でも、文字列を対象とした分岐処理は、ユーザー入力の判定、設定値の読み込み、APIレスポンスの振り分けなど、実務のあらゆる場面で登場します。
かつてのC#では、複数の条件を扱う際に (if-else if) を多用する傾向がありましたが、現在のC#では switch文の機能が大幅に強化されており、より簡潔で読みやすい記述が可能 になっています。
本記事では、C#における switch 文を用いた文字列判定の基本から、C# 8.0以降で主流となった switch式 の活用、さらには実務で陥りやすい大文字・小文字の区別や、 NullReferenceException を防ぐための注意点まで、プロフェッショナルな視点で詳しく解説します。
C#におけるswitch文の基本(文字列判定)
C#の switch 文は、数値だけでなく文字列を直接判定の対象にすることが可能です。
これはJavaなどの他の言語と同様の感覚で記述できますが、C#特有のルールも存在します。
まずは、最も伝統的な switch 文の書き方を確認しましょう。
従来のswitch文による文字列分岐
従来の switch 文では、 case ラベルに判定したい文字列を指定し、それぞれの処理の終わりに break 文を記述します。
using System;
public class Program
{
public static void Main()
{
string userRole = "Admin";
// 従来のswitch文による文字列判定
switch (userRole)
{
case "Admin":
Console.WriteLine("管理者権限でログインしました。");
break;
case "Editor":
Console.WriteLine("編集者権限でログインしました。");
break;
case "Guest":
Console.WriteLine("ゲスト権限でログインしました。");
break;
default:
Console.WriteLine("権限が不明です。アクセスを拒否しました。");
break;
}
}
}
管理者権限でログインしました。
この記述方法のメリットは、 分岐先が明確で、構造が理解しやすいこと です。
しかし、処理が一行で済むような単純な代入処理の場合、コードが冗長になりがちであるという欠点もあります。
C# 8.0以降の主流:switch式による洗練された記述
C# 8.0で導入された switch式 は、従来の switch 文をより簡潔に記述できるようにしたものです。
これは「文 (Statement)」ではなく「式 (Expression)」であるため、 値を直接返すことができる のが最大の特徴です。
switch式の構文とメリット
文字列を判定して、その結果を変数に代入する場合、 switch 式を使うとコードの行数を劇的に減らすことができます。
using System;
public class Program
{
public static void Main()
{
string command = "start";
// switch式を用いた文字列判定と値の返却
string message = command switch
{
"start" => "システムを開始します。",
"stop" => "システムを停止します。",
"wait" => "一時待機中です。",
_ => "無効なコマンドです。" // デフォルトケース(破棄パターン)
};
Console.WriteLine(message);
}
}
システムを開始します。
この記法では、 case や break を書く必要がなく、 => (ラムダ演算子に似た記号) を使用して結果を指定します。
また、 default キーワードの代わりに _ (アンダースコア) を使用して「それ以外」のケースを表現します。
複数の値を同じ処理にまとめる
複数の文字列に対して同じ結果を返したい場合、従来の switch 文では case を並べて記述していましたが、 switch 式でも同様のロジックが可能です。
string category = "apple";
string type = category switch
{
"apple" or "orange" or "banana" => "Fruit",
"carrot" or "potato" => "Vegetable",
_ => "Unknown"
};
このように or パターンを使用することで、直感的に条件を統合できます。
これは C# 9.0 で導入されたパターンマッピングの強化によるものです。
文字列判定における重要課題:大文字・小文字の区別
C#の文字列比較は、デフォルトで 「序数比較 (Ordinal Comparison)」かつ「大文字・小文字を区別する」 設定になっています。
つまり、 "Admin" と "admin" は異なる文字列として判定されます。
実務では、ユーザーの入力揺れを許容するために、これらを同一視したいケースが多くあります。
StringComparisonを指定する方法の限界
残念ながら、 switch 文の条件式の中で直接 StringComparison.OrdinalIgnoreCase を指定することはできません。
そのため、以下のいずれかの手法を取るのが一般的です。
1. 判定前に正規化(ToLower/ToUpper)する
最も一般的な方法は、判定対象の文字列をあらかじめ ToLower() または ToUpper() で統一することです。
string input = "ADMIN";
switch (input.ToLower())
{
case "admin":
// 処理
break;
}
ただし、この手法には 「inputがnullの場合にNullReferenceExceptionが発生する」 というリスクがあります。
2. パターンマッピングとwhen句を活用する
より安全かつ高度な判定を行いたい場合は、 when 句を使用したパターンマッピングが有効です。
string status = "ACTIVE";
string result = status switch
{
var s when string.Equals(s, "active", StringComparison.OrdinalIgnoreCase) => "有効な状態です",
var s when string.Equals(s, "inactive", StringComparison.OrdinalIgnoreCase) => "無効な状態です",
_ => "不明なステータス"
};
この方法であれば、元の文字列の状態を変えずに、詳細な比較ロジックを組み込むことができます。
Nullの取り扱いと安全な実装
文字列を扱う際に避けて通れないのが null値 の考慮です。
switch 文に渡される変数が null である可能性がある場合、適切なハンドリングを行わないとプログラムが予期せぬ挙動を示すことがあります。
switch文でのnull判定
C#の switch 文は、明示的に case null: を記述することで null を安全に処理できます。
string? fileName = null;
switch (fileName)
{
case null:
Console.WriteLine("ファイル名が指定されていません。");
break;
case "data.csv":
Console.WriteLine("CSVファイルを処理します。");
break;
default:
Console.WriteLine("その他のファイルを処理します。");
break;
}
switch式でのnull判定
switch 式でも同様に null をケースの一つとして扱えます。
string? input = null;
string output = input switch
{
"A" => "タイプA",
"B" => "タイプB",
null => "入力が空です",
_ => "未知のタイプ"
};
もし null ケースを記述せず、実際に null が渡された場合、 _ (デフォルトケース) にマッチします。
デフォルトケースも存在しない場合は、 SwitchExpressionException がスローされるため注意が必要です。
複雑な条件を組み合わせる「パターンマッチング」
C#の進化に伴い、 switch は単なる値の合致チェックを超え、複雑な条件式を記述できるツールへと変貌しました。
プロパティパターンによる判定
例えば、文字列そのものだけでなく、 「文字列の長さ」 に基づいて分岐させることも可能です。
string password = "mysecretpassword";
string safety = password switch
{
{ Length: < 8 } => "短すぎます",
{ Length: >= 8 } and "password" => "推測されやすいパスワードです",
_ => "適切な長さです"
};
このように、オブジェクトのプロパティ(この場合は Length )を対象に条件を指定できるのが プロパティパターン です。
関係パターンと論理パターン
数値と文字列を組み合わせた複雑なロジックも、 and や or を使ってスマートに記述できます。
string input = "SampleText";
string evaluation = input switch
{
null or "" => "空の入力です",
{ Length: > 0 } and { Length: <= 5 } => "短いテキストです",
_ => "十分な長さのテキストです"
};
パフォーマンスの観点:switch vs if-else
多くの開発者が気になるのが、 switch 文を使用した際のパフォーマンスです。
結論から述べると、 対象となるケース数が多い場合、switch文はif-else文よりも高速に動作する可能性が高い です。
コンパイラによる最適化
C#のコンパイラは、 switch 文に含まれる文字列の数や内容を分析し、最適な実行コードを生成します。
| ケース数 | 最適化の手法 |
|---|---|
| 数個程度 | if-else と同等の逐次比較が行われることが多い。 |
| 多数 (約7個以上) | ハッシュテーブル が内部的に生成され、定数時間でのジャンプが試みられる。 |
大量の文字列定数を判定する場合、コンパイラは Dictionary に近い仕組みを使用して、一気にジャンプ先を特定します。
一方、 if-else は上から順番に比較を繰り返すため、条件が後ろにあるほど処理時間が長くなります。
したがって、 可読性の観点だけでなく、パフォーマンスの観点からも switch文の利用が推奨されます。
switch文を使用する際のベストプラクティス
実務でメンテナンス性の高いコードを書くために、以下のポイントを意識してください。
- マジックストリングの回避
ケース例として
"Admin"のように文字列を直接記述するのではなく、const stringやenum(列挙型)の使用を検討する。ただし外部APIの文字列をそのまま扱う必要がある場合は例外とする。
- default(または _)を必ず含める
switch やパターンマッチで
default(または_)を必ず含め、予期しない値が入力された際は何もしないのではなく、エラーログを出力したりデフォルト値を返したりしてバグの早期発見に努める。- 副作用のある処理を避ける
特に
switch式の中では計算や値の返却に専念させ、メソッド呼び出しで大きく状態を変化させるような副作用のある処理は避ける。関数の純粋性(pure function)を保つよう設計する。
まとめ
C#の switch 文による文字列判定は、言語のバージョンアップとともに非常に強力な機能へと進化してきました。
- 従来の switch 文 は、複雑な手続き型の処理を分岐させるのに適しています。
- 最新の switch 式 は、値を返す処理を簡潔に記述でき、コードのノイズを大幅に削減します。
- パターンマッチング を活用することで、文字列の長さや
null判定、複合条件を美しく記述できます。 - パフォーマンス面 でも、コンパイラによるハッシュテーブル最適化の恩恵を受けられるため、多分岐処理において非常に有利です。
文字列操作はアプリケーション開発の根幹を成す部分です。
今回紹介したテクニックを駆使して、安全で読みやすく、そして高速なC#プログラムの実装に役立ててください。
特に switch 式とパターンマッチングの組み合わせは、現代的なC#コードを書く上で必須のスキルと言えるでしょう。






