Typmuster

Tip

Dieser Artikel ist Teil des Abschnitts "Grundlagen" für Entwickler, die bereits mindestens eine Programmiersprache kennen und C# erlernen. Beginnen Sie mit der Übersicht über den Musterabgleich , wenn Muster für Sie neu sind. Vollständige Kompatibilitätsregeln finden Sie unter Deklarations- und Typmuster in der Sprachreferenz.

Ein Typmuster wird auf einen Eingabeausdruck angewendet. C# wertet den Ausdruck aus und testet dann, ob der resultierende Wert ungleich NULL ist und der Laufzeittyp mit dem angegebenen Typ kompatibel ist. Ein Typmuster meldet nur, ob der Typtest erfolgreich war. Eine Variable wird nicht deklariert.

Eine Ja-Nein-Frage stellen

In einem Zustellsystem ist IRouteStop ein Fähigkeitsvertrag für Ziele, die von der Routenplanung akzeptiert werden. CanRoute überprüft, ob das geprüfte Ziel über diese Fähigkeit verfügt, und der boolesche Wert bestimmt, ob das Ziel in den Routenplanungs-Workflow aufgenommen wird. Der Workflow benötigt nur eine Ja-oder-Nein-Antwort und liest keine Mitglieder von route-stop, sodass ein Typmuster ohne gebundene Variable passt.

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

Der Eingabeausdruck ist destinationund IRouteStop der Typ, der getestet wird. Wählen Sie ein Typmuster aus, wenn die Antwort nur "Ja" oder "Nein" lautet. Wenn die passende Verzweigung über IRouteStop eine Adresse lesen oder einen anderen Member aufrufen muss, wählen Sie stattdessen ein Deklarationsmuster aus, damit die Verzweigung über eine Variable dieses Typs verfügt.

Note

Möglicherweise wird auch destination is IRouteStop _ angezeigt. Diese Syntax ist ein Deklarationsmuster, in dem _ keine Variable beibehalten wird. Er führt dieselbe Typprüfung aus, wenn beide Formen gültig sind, aber destination is IRouteStop bringt die Absicht, dass es sich nur um einen Test handelt, direkter zum Ausdruck.

Abgleichen von Klassen und Schnittstellen

Im Übermittlungssystem IRouteStop wird der Funktionsvertrag für Routenplanungsziele definiert, während RouteStop es sich um eine Basisklasse handelt, die allgemeine Routenstoppdaten und Implementierungen bereitstellt. ExpressRouteStop ist eine spezialisierte Klasse, die von RouteStop abgeleitet ist. Im Beispiel wird ein ausgewerteter Wert getestet, sodass die Ausgabe alle drei kompatiblen Typen veranschaulichen kann. Jeder Test benötigt nur ein boolesches Ergebnis, sodass keine erfasste Variable erforderlich ist.

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}");
}

Der ausgewertete Wert ist ein ExpressRouteStop. Die Ausgabe zeigt, dass es seiner exakten Klasse, seiner RouteStop-Basisklasse und der IRouteStop-Schnittstelle entspricht, die RouteStop implementiert.

Ausführliche Kompatibilitätsregeln und Edgefälle finden Sie in der Typmusterreferenz.

Mehrere Routentypen

In einem Supportsystem SupportRequest ist die Basisklasse für spezialisierte Anforderungsklassen wie PasswordResetRequest und BillingQuestion. Ein Schalterarm koppelt ein Muster mit dem Ergebnis, das zurückgegeben werden soll, wenn dieses Muster übereinstimmt. Jeder Arm gibt den Namen einer Verarbeitungswarteschlange zurück, und der letzte Arm stellt eine Fallbackwarteschlange für andere ausgewertete Werte bereit. Die ausgewählte Warteschlange hängt nur vom Laufzeittyp des ausgewerteten Werts ab, sodass sich Typmuster eignen, da kein Element der Anforderung ausgelesen wird.

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

Jeder Arm beantwortet eine Typfrage und gibt die Warteschlange zurück, die diese Anforderung verarbeitet. Wenn ein Arm Elemente einer Anfrage lesen muss, verwenden Sie ein Deklarationsmuster, um den passenden Wert in einer Variablen zu erfassen.

Schaltarme werden von oben nach unten betrachtet. Platzieren Sie eine spezialisierte Klasse vor der Basisklasse. Andernfalls kann der Arm der Basisklasse jeder Instanz der spezialisierten Klasse entsprechen, wodurch der spätere Arm nicht erreichbar ist.

Optional: Verwenden eines Typparameters als getesteter Typ

Dieses optionale Beispiel baut auf generischen Typen und Methoden auf. Ein Typparameter wie TRequest ist ein Platzhalter für einen Typ, den der Aufrufer angibt. Ein Stapel eingehender Anfragen kann mehrere Anfragetypen enthalten, und der Aufrufer übergibt ConfidentialRequest, um zu prüfen, ob eine der Anfragen eine vertrauliche Verarbeitung erfordert. Das boolesche Ergebnis wählt die vertrauliche Behandlung für den gesamten Batch aus und erzeugt eine sichtbare Statusmeldung. Ein Typmuster mit einem Typparameter passt, da nur das Vorhandensein einer übereinstimmenden Anforderung wichtig ist, sodass das übereinstimmende Objekt nicht beibehalten werden muss.

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;
}

Wenn der Aufrufer die übereinstimmende Anforderung selbst benötigt hat, wäre ein Such- oder Filtervorgang, der übereinstimmende Elemente zurückgibt, geeigneter.

Siehe auch