リレーショナル パターン、論理パターン、およびかっこでつながれたパターン

Tip

この記事は、少なくとも 1 つのプログラミング言語を既に知っており、C# を学習している開発者向けの 基礎 セクションの一部です。 パターンが初めて使用される場合は、パターン マッチングの概要 から始めます。 完全な言語ルールについては、言語リファレンス のリレーショナル パターン と 論理パターン を参照してください。

リレーショナル パターンと論理パターンでは、範囲、代替手段、除外について説明します。 次の方法では、それらを組み合わせて温度を分類します。

static string ClassifyTemperature(int temperature) =>
    temperature switch
    {
        < 0 => "Below freezing",
        >= 18 and <= 24 => "Comfortable",
        (>= 0 and < 10) or > 30 => "Far outside the comfortable range",
        _ => "Cool or warm"
    };

temperature式はパターン入力です。 C# はそれを 1 回評価し、各スイッチ アームは結果の値をテストします。 アームは以下のテストを実施します。

  • < 0 1 つの境界をテストします。
  • >= 18 and <= 24 範囲をテストします。
  • (>= 0 and < 10) or > 30 2 つの代替範囲をテストします。

この記事では、パターンと命令型の条件の両方を示します。これにより、各フォームを学習し、同じ決定を表す方法を比較できます。 1 つの条件は、どちらの形式でも似ています。 パターンを使用すると、結果の横に選択肢を維持することで、一連の関連ブランチを読みやすくすることができます。 コードを理解しやすくするフォームを選択します。

リレーショナル パターンと値を比較する

リレーショナル パターンでは、<、>、<=、または>=を使用して、そのパターン入力をコンパイル時定数と比較します。 コンパイル時定数は、プログラムのコンパイル中にコンパイラが評価できる値です。 数値リテラルと文字リテラル、および互換性のある数値型または文字型の const 変数が代表的な例です。 通常の変数、プロパティ、メソッド呼び出し、 static readonly フィールドはコンパイル時定数ではありません。 開始例では、 >= 18 と <= 24 の両方で、同じ評価された temperature 値をテストします。

同じリレーショナル シンボルは、通常の式またはパターンに表示できます。 次の例では、温度を使って両方の形式を示します。

static void ShowExpressionAndPattern(int temperature, int threshold)
{
    bool belowThreshold = temperature < threshold;
    bool belowFreezing = temperature is < 0;

    string description = temperature switch
    {
        < 0 => "Freezing",
        0 => "Freezing point",
        > 0 => "Above freezing"
    };

    Console.WriteLine(
        $"Below threshold: {belowThreshold}; " +
        $"below freezing: {belowFreezing}; {description}");
}

temperature < threshold は 関係式です。 両方のオペランドを評価し、 boolを生成します。 どちらのオペランドにも、非連続式を指定できます。

temperature is < 0では、temperatureはパターン入力式です。 C# はそれを評価し、リレーショナル パターン < 0 結果の値をテストします。 スイッチ アーム < 0 => "Freezing"では、 switch 前の式によって入力が提供されるため、パターンには < 0のみが含まれます。

式は、変数thresholdとtemperatureを比較できます。 リレーショナル パターン オペランドはコンパイル時定数である必要があるため、比較値が変数の場合はリレーショナル式を使用します。 比較値が一定の場合、どちらの形式でも機能します。

右オペランドが定数の場合は、主に読みやすくするために選択します。 多くの場合、関係式は 1 つの直接比較に適合します。 リレーショナルパターンは他のパターンと組み合わせることができ、複数の範囲が switch の結果に対応する場合に自然に適しています。

条件と論理パターンを組み合わせる

論理パターンは、 パターン演算子 and、 or、および notでパターンを結合または否定します。

  • and パターンは、両方の入れ子になったパターンが一致する場合に一致します。
  • or パターンは、入れ子になったパターンのいずれかが一致する場合に一致します。
  • not パターンは、入れ子のパターンが失敗したときに成功します。

最初の例では、 and を使用して範囲を記述し、 or を使用して代替手段を記述します。 not パターンでは、status is not Status.Completeのように値を除外できます。 次のメソッドは両方のフォームを示しているため、構文を学習し、同じテストを表現する方法を比較できます。

static bool IsWeekendPattern(DayOfWeek day) =>
    day is DayOfWeek.Saturday or DayOfWeek.Sunday;

static bool IsWeekendImperative(DayOfWeek day) =>
    day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;

パターン フォームでは、 orによって結合された 2 つの定数パターンが使用されます。 命令形式では、条件付き OR 演算子 ||で結合された 2 つの等値式が使用されます。 どちらのフォームも、この単一の条件に対して簡潔で明確です。 周囲のコードに最適なフォームを選択します。 パターンは、多くの場合、最初の例のように、 switchのいくつかの関連する選択肢を明確にします。

パターン演算子は、ブール式ではなくパターンを形成します。 and は、パターンの組み合わせ、パターンの代替に or 、パターン否定に not に対応します。 ブール式では、 &&、 ||、および !を使用します。 複数のパターンの代替方法で同じ結果が得られた場合は、 or を選択します。 除外されたパターンを表す場合は not を選択すると、受け入れ可能なすべての値を一覧表示するよりも明確になります。

括弧を使ってパターンをグループ化する

かっこで囲まれたパターンでは、かっこを使用して、入れ子になったパターンのグループ化方法を表示または変更します。 結合性 は、括弧を記述しない場合の暗黙的なグループ化と同様に、演算子がどのパターンオペランドをひとまとまりとして扱うかを決定します。 C# では、次のバインド順序を指定します。

  1. not
  2. and
  3. or

次のテストでは、優先度 1 から 3 または特別な優先度 9 を受け入れます。

static bool IsAcceptedPriority(int priority) =>
    priority is (>= 1 and <= 3) or 9;

コンパイラは、orをandの前にグループ化します。 かっこを使用すると、目的のグループ化が明示的になり、2 つの代替手段 (1 から 3、または 9 の範囲) を簡単に確認できます。 読みやすくするために、パターンが and と orを混在させる場合、または複合パターンに適用 not 場合は常にかっこを使用します。 丸括弧は、not (>= 1 and <= 3) にあるように、既定のグループ化方法を変更することもできます。

入れ子になったパターンのランタイム チェック順序は指定されておらず、パターン演算子は、短絡ブール型の規則ではなく、パターンマッチング規則に従います。 結果がチェック順序に依存しないように、入れ子になったパターンを記述します。

別の条件に対して when ガードを使用する

論理パターンは、入れ子になったパターンが入力値自体を記述する場合に最適です。 when ガードは、case ラベルまたはスイッチ アームの追加のブール条件です。 決定がパターン入力とは別の情報にも依存する場合は、ガードを使用します。

次の警告は、温度と個別の isOutdoors 値によって異なります。

static string GetHeatWarning(int temperature, bool isOutdoors) =>
    temperature switch
    {
        > 35 when isOutdoors => "High heat outdoors",
        > 35 => "High heat",
        _ => "No heat warning"
    };

リレーショナル パターン > 35 では、 temperature 入力について説明します。 ガード when isOutdoors は別の値をチェックします。 条件にメソッド呼び出しが必要な場合や、パターン構文が明確に表現されないブール式が必要な場合にも、ガードを使用することをお勧めします。

リレーショナル パターンと論理パターンは、入力の許可された図形または値を、特に複数のスイッチ アーム間で見やすくする場合に使用します。 直接条件がより単純に指定されている場合は、通常のブール式を使用します。 切り替えの選択が別の値に依存する場合、またはブール式として表現される条件に応じて、 when ガードを使用します。

こちらも参照ください