型パターン

Tip

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

型パターンが入力式に適用されます。 C# は式を評価し、結果の値が null 以外で、実行時の型が指定された型と互換性があるかどうかをテストします。 型パターンでは、型テストが成功したかどうかのみが報告されます。 変数は宣言されません。

「はい」か「いいえ」で答えられる質問をする

配信システムでは、 IRouteStop は、ルート計画によって受け入れられる宛先の機能コントラクトです。 CanRoute は、評価された宛先がその機能を持っているかどうかをテストし、そのブール値の結果によって、宛先がルート計画ワークフローに入るかどうかを決定します。 ワークフローで必要なのは yesor-no 回答のみで、ルートストップ メンバーを読み取らないので、キャプチャされた変数のない型パターンが適合します。

static bool CanRoute(object? destination) =>
    destination is IRouteStop;

入力式は destinationされ、 IRouteStop はテスト対象の型です。 回答が "はい" または "いいえ" の場合は、型パターンを選択します。 一致するブランチがアドレスを読み取る必要がある場合、または IRouteStopを介して別のメンバーを呼び出す必要がある場合は、代わりに 宣言パターン を選択して、ブランチにその型の変数を含めます。

Note

destination is IRouteStop _も表示される場合があります。 この構文は宣言パターンであり、 _ は変数が保持されていないことを意味します。 両方のフォームが有効な場合は同じ型テストを実行しますが、 destination is IRouteStop はテスト専用の意図をより直接示します。

クラスとインターフェイスを照合する

配信システムでは、 IRouteStop はルート計画の宛先の機能コントラクトを定義しますが、 RouteStop は共通のルートストップ データと実装を提供する基本クラスです。 ExpressRouteStop は、 RouteStopから派生した特殊なクラスです。 この例では、1 つの評価値をテストして、3 つの互換性のある型すべてを出力で示すことができます。 各テストにはブール値の結果のみが必要であるため、キャプチャされた変数は必要ありません。

interface IRouteStop { }

abstract class RouteStop(string street) : IRouteStop
{
    public string Street { get; } = street;

    public string GetDisplayName() => Street;
}

sealed class ExpressRouteStop(string street) : RouteStop(street)
{
}

static void ShowCompatibility()
{
    object destination = new ExpressRouteStop("8 Oak Avenue");

    Console.WriteLine($"Exact class: {destination is ExpressRouteStop}");
    Console.WriteLine($"Base class: {destination is RouteStop}");
    Console.WriteLine($"Interface: {destination is IRouteStop}");
}

評価された値は ExpressRouteStopです。 出力は、その正確なクラス、そのRouteStop基底クラス、およびRouteStop実装するIRouteStop インターフェイスと一致することを示しています。

互換性規則とエッジ ケースの詳細については、 型パターンのリファレンスを参照してください

複数の種類をルーティングする

サポート システムでは、 SupportRequest は、 PasswordResetRequestBillingQuestionなどの特殊な要求クラスの基本クラスです。 スイッチ アームは、パターンと結果を組み合わせて、そのパターンが一致したときに返します。 各アームは処理キューの名前を返し、最後のアームは他の評価値のフォールバック キューを提供します。 選択したキューは、評価された値の実行時の型にのみ依存するため、要求メンバーが読み取らないため、型パターンが適合します。

static string RouteRequest(object request) =>
    request switch
    {
        PasswordResetRequest => "Identity queue",
        BillingQuestion => "Billing queue",
        SupportRequest => "General support queue",
        _ => "Intake queue"
    };

各アームは型の質問に答え、その要求を処理するキューを返します。 arm が要求メンバーを読み取る必要がある場合は、宣言パターンを使用して、変数内の一致する値をキャプチャします。

スイッチアームは上から下に見なされます。 基底クラスの前に特殊なクラスを配置します。 それ以外の場合、基底クラスの arm は特殊化されたクラスのすべてのインスタンスと一致し、後のアームに到達できなくなります。

省略可能: テスト対象の型として型パラメーターを使用する

この省略可能な例は 、ジェネリック型とメソッドに基づいています。 TRequestなどの型パラメーターは、呼び出し元が提供する型のプレースホルダーです。 受信要求バッチには複数の要求の種類を含めることができます。呼び出し元は、要求に機密処理が必要かどうかをテストするために ConfidentialRequest を提供します。 ブール値の結果は、バッチ全体の機密処理を選択し、表示状態メッセージを生成します。 型パラメーターを持つ型パターンは、一致する要求の存在のみが重要であるため、一致するオブジェクトを保持する必要がないため、適合します。

static void ShowConfidentialBatchHandling()
{
    object[] incomingRequests = [new BillingQuestion(), new ConfidentialRequest()];
    bool requiresConfidentialHandling =
        ContainsRequestOfType<ConfidentialRequest>(incomingRequests);

    Console.WriteLine(requiresConfidentialHandling
        ? "Send the entire batch to confidential handling."
        : "Send the batch to standard handling.");
}

static bool ContainsRequestOfType<TRequest>(IEnumerable<object> requests)
{
    foreach (object request in requests)
    {
        if (request is TRequest)
        {
            return true;
        }
    }

    return false;
}

呼び出し元が一致する要求自体を必要とする場合は、一致する項目を返す検索またはフィルター操作の方が適切です。

こちらも参照ください