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

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

次の例は、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 式が網羅的になります。

重要

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

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

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

ケース ガード

アームの式の評価の条件を指定するのに十分な表現がパターンにない場合があります。 このような場合は、''ケース ガード'' を使用できます。 "ケース ガード" は、パターンの一致と共に満たす必要がある追加条件です。 ケース ガードはブール式にする必要があります。 次の例に示すように、パターンの後に続く 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 パターンを入れ子にしたプロパティ パターンを使用しています。

網羅的でない switch 式

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

ヒント

switch 式ですべての可能な入力値が確実に処理されるようにするには、破棄パターンを使用した switch 式アームを指定します。

C# 言語仕様

詳細については、機能提案メモの「switch」のセクションを参照してください。

関連項目