switch expression - switch キーワードを使用したパターン マッチング式

switch式を使用して、候補となる式の一覧から 1 つの式を評価します。 評価は、入力式とのパターン一致に基づいています。 ステートメント コンテキストでswitchのようなセマンティクスをサポートするswitch ステートメントについては、switchに関する記事の「 ステートメント」セクションを参照してください。

C# 言語リファレンスには、C# 言語の最新リリース バージョンが記載されています。 また、今後の言語リリースのパブリック プレビューの機能に関する初期ドキュメントも含まれています。

このドキュメントでは、言語の最後の 3 つのバージョンまたは現在のパブリック プレビューで最初に導入された機能を特定します。

ヒント

C# で機能が初めて導入された時期を確認するには、 C# 言語バージョン履歴に関する記事を参照してください。

次の例では、 switch 式を示します。 オンライン マップ内の視覚的な方向を表す enum の値を、対応するカーディナル方向に変換します。

public static class SwitchExample
{
    public enum Direction
    {
        Up,
        Down,
        Right,
        Left
    }

    public enum Orientation
    {
        North,
        South,
        East,
        West
    }

    public static Orientation ToOrientation(Direction direction) => direction switch
    {
        Direction.Up    => Orientation.North,
        Direction.Right => Orientation.East,
        Direction.Down  => Orientation.South,
        Direction.Left  => Orientation.West,
        _ => throw new ArgumentOutOfRangeException(nameof(direction), $"Not expected direction value: {direction}"),
    };

    public static void Main()
    {
        var direction = Direction.Right;
        Console.WriteLine($"Map view direction is {direction}");
        Console.WriteLine($"Cardinal orientation is {ToOrientation(direction)}");
        // Output:
        // Map view direction is Right
        // Cardinal orientation is East
    }
}

前の例は、 switch 式の基本的な要素を示しています。

  • 式の後に switch キーワードが続きます。 前の例では、 direction メソッド パラメーターです。
  • コンマで区切られた switch 式の腕。 各 switch 式アームには、 パターン、省略可能な ケース ガード、 => トークン、および式が含 まれています。

前の例では、 switch 式は次のパターンを使用します。

  • 定数パターン: Direction列挙体の定義された値を処理します。
  • 破棄パターン: Direction列挙体の対応するメンバーを持たない整数値 (たとえば、(Direction)10) を処理します。 このパターンにより、 switch 式が 完全になります。

Von Bedeutung

switch式でサポートされるパターンとその他の例については、「パターン」を参照してください。

switch式の結果は、パターンが入力式と一致し、ケース ガード (存在する場合) がswitchに評価される最初のtrue式アームの式の値です。 switch式のアームは、テキストの順序で評価されます。

上位のswitch式アームがそのすべての値と一致するため、より低いswitch式アームを選択できない場合、コンパイラはエラーを生成します。

ケースガード

パターンは、腕の式の評価の条件を指定するのに十分な表現力がない可能性があります。 このような場合は、 ケース ガードを使用します。 ケース ガードは、一致するパターンと一緒に満たす必要があるもう 1 つの条件です。 ケース ガードはブール式である必要があります。 次の例に示すように、パターンに従う when キーワードの後にケース ガードを指定します。

public readonly struct Point
{
    public Point(int x, int y) => (X, Y) = (x, y);
    
    public int X { get; }
    public int Y { get; }
}

static Point Transform(Point point) => point switch
{
    { X: 0, Y: 0 }                    => new Point(0, 0),
    { X: var x, Y: var y } when x < y => new Point(x + y, y),
    { X: var x, Y: var y } when x > y => new Point(x - y, y),
    { X: var x, Y: var y }            => new Point(2 * x, 2 * y),
};

前の例では、入れ子になった var パターンを 持つプロパティ パターンを使用します。

Nonexhaustive スイッチ式

switch式のパターンのいずれも入力値と一致しない場合、ランタイムは例外をスローします。 .NET Core 3.0 以降のバージョンでは、例外は System.Runtime.CompilerServices.SwitchExpressionException です。 .NET Framework では、例外は InvalidOperationException です。 ほとんどの場合、 switch 式が可能なすべての入力値を処理しない場合、コンパイラは警告を生成します。 可能なすべての入力が処理されない場合、リスト パターンでは警告は生成されません。

共用体型の場合、すべてのケース型を処理する場合、switch式は完全です。 キャッチオール アームは必要ありません。 共用体の Value プロパティの null 状態が "null である可能性があります" の場合は、警告を回避するために null も処理する必要があります。 詳細については、「 和集合の網羅性」を参照してください。

新しく割り当てられた共用体配列の要素やdefaultで作成された値など、すべてのケース型が null できない場合でも、既定で生成された共用体にnullを含めることができます。 コンパイラは、その状況で省略された null arm について必ずしも警告するわけではありませんが、arm が一致しない場合でもスイッチはスローします。 既定の共用体の内容がスイッチに到達できる場合は、 null を処理します。 新しいケース タイプを追加しても完全でない警告が生成されるように、 null アームを var または破棄アームに優先します。

ヒント

switch式が可能なすべての入力値を処理することを保証するには、switchを持つ式アームを指定します。

C# 言語仕様

詳細については、switchの「式」セクションを参照してください。

こちらも参照ください