Ereignisse
17. März, 23 Uhr - 21. März, 23 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrierenDieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge durch, um die neuesten Features, Sicherheitsupdates und den technischen Support zu nutzen.
Ein Muster ist eine syntaktische Form, die mit dem is
Operator (§12.12.12) und in einem switch_statement (§13.8.3) verwendet werden kann, um das Shape der Daten auszudrücken, mit denen eingehende Daten verglichen werden sollen. Ein Muster wird auf den Ausdruck einer Switch-Anweisung oder auf eine relational_expression getestet, die sich auf der linken Seite eines is
Operators befindet, von denen jeder als Mustereingabewert bezeichnet wird.
Ein Muster kann eine der folgenden Formen aufweisen:
pattern
: declaration_pattern
| constant_pattern
| var_pattern
;
Ein declaration_pattern und ein var_pattern können zur Deklaration einer lokalen Variablen führen.
Jedes Musterformular definiert den Satz von Typen für Eingabewerte, auf die das Muster angewendet werden kann. Ein Muster P
gilt für einen Typ T
, wenn T
es sich um die Typen handelt, deren Werte das Muster möglicherweise abgleichen kann. Es handelt sich um einen Kompilierungsfehler, wenn ein Muster P
in einem Programm angezeigt wird, um einem Mustereingabewert (§11.1) des Typs T
zu entsprechen, falls P
nicht zutreffend T
.
Beispiel: Im folgenden Beispiel wird ein Kompilierungszeitfehler generiert, da der Kompilierungszeittyp
v
lautetTextReader
. Eine Variable vom TypTextReader
kann niemals einen Wert aufweisen, der referenzkompatibel ist mitstring
:C#
TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }
Im Folgenden wird jedoch kein Kompilierungszeitfehler generiert, da der Kompilierungszeittyp
v
lautetobject
. Eine Variable des Typsobject
könnte einen Wert aufweisen, der referenzkompatibel ist mitstring
:C#
object v = Console.In; if (v is string s) { // code assuming v is a string }
Endbeispiel
Jedes Musterformular definiert den Wertesatz, für den das Muster dem Wert zur Laufzeit entspricht .
Ein declaration_pattern wird verwendet, um zu testen, ob ein Wert einen bestimmten Typ aufweist, und wenn der Test erfolgreich ist, den Wert in einer Variablen dieses Typs bereitstellen.
declaration_pattern
: type simple_designation
;
simple_designation
: single_variable_designation
;
single_variable_designation
: identifier
;
Der Laufzeittyp des Werts wird anhand der im Is-Type-Operator (§12.12.12.12.12.1) angegebenen Regeln im Muster getestet. Wenn der Test erfolgreich ist, entspricht das Muster diesem Wert. Es handelt sich um einen Kompilierungszeitfehler, wenn der Typ ein Nullwerttyp ist (§8.3.12). Dieses Musterformular entspricht niemals einem null
Wert.
Hinweis: Der Is-Type-Ausdruck
e is T
und das Deklarationsmustere is T _
sind gleichwertig, wennT
kein Nullwerttyp vorhanden ist. Endnote
Bei einem Mustereingabewert (§11.1) e, wenn die simple_designation der Bezeichner _
ist, wird ein Verwerfen (§9.2.9.1) und der Wert von e nicht an nichts gebunden. (Obwohl eine deklarierte Variable mit dem Namen _
zu diesem Zeitpunkt im Bereich enthalten sein kann, wird diese benannte Variable in diesem Kontext nicht angezeigt.) Wenn simple_designation ein anderer Bezeichner ist, wird eine lokale Variable (§9.2.9) des durch den angegebenen Bezeichner benannten Typs eingeführt. Diese lokale Variable wird dem Wert des Mustereingabewerts zugewiesen, wenn das Muster dem Wert entspricht .
Bestimmte Kombinationen des statischen Typs des Mustereingabewerts und des angegebenen Typs werden als inkompatibel betrachtet und führen zu einem Kompilierungszeitfehler. Ein Wert des statischen Typs E
wird als Muster angegeben, das mit dem Typ T
kompatibel ist, wenn eine Identitätskonvertierung, eine implizite oder explizite Verweiskonvertierung, eine Boxkonvertierung oder eine Unboxing-Konvertierung von E
zu T
, oder wenn T
E
es sich um einen geöffneten Typ (§8.4.3) handelt. Ein Deklarationsmuster, das einen Typ T
benennt, gilt für jeden Typ E
, für den E
das Muster kompatibel ist T
.
Hinweis: Die Unterstützung für offene Typen kann am nützlichsten sein, wenn Typen überprüft werden, die entweder Struktur- oder Klassentypen sein können, und boxen ist zu vermeiden. Endnote
Beispiel: Das Deklarationsmuster ist nützlich, um Laufzeittypentests von Referenztypen durchzuführen und das Idiom zu ersetzen.
C#
var v = expr as Type; if (v != null) { /* code using v */ }
mit der etwas prägnanteren
C#
if (expr is Type v) { /* code using v */ }
Endbeispiel
Es handelt sich um einen Fehler, wenn der Typ ein Nullwerttyp ist.
Beispiel: Das Deklarationsmuster kann verwendet werden, um Werte von nullablen Typen zu testen: Ein Wert vom Typ
Nullable<T>
(oder ein BoxedT
) entspricht einem TypmusterT2 id
, wenn der Wert ungleich NULL ist undT2
T
oder ein Basistyp oder eine Schnittstelle vonT
. Beispiel: im CodefragmentC#
int? x = 3; if (x is int v) { /* code using v */ }
Die Bedingung der
if
Anweisung befindettrue
sich zur Laufzeit, und die Variablev
enthält den Wert3
des Typsint
innerhalb des Blocks. Endbeispiel
Ein constant_pattern wird verwendet, um den Wert eines Mustereingabewerts (§11.1) anhand des angegebenen Konstantenwerts zu testen.
constant_pattern
: constant_expression
;
Ein Konstantenmuster P
gilt für einen Typ T
, wenn eine implizite Konvertierung vom konstanten Ausdruck in P
den Typ T
vorhanden ist.
Bei einem Konstantenmuster P
ist der konvertierte Wert
Bei einem Mustereingabewert e und einem konstanten Muster P
mit konvertiertem Wert v
P
dem Wert e, wenn das Ergebnis des Ausdrucks e == v
lautettrue
; andernfallsP
entspricht dem Wert e , wenn object.Equals(e, v)
zurückgegeben wird true
.Beispiel: Die
switch
Anweisung in der folgenden Methode verwendet fünf Konstantenmuster in ihren Fallbeschriftungen.C#
static decimal GetGroupTicketPrice(int visitorCount) { switch (visitorCount) { case 1: return 12.0m; case 2: return 20.0m; case 3: return 27.0m; case 4: return 32.0m; case 0: return 0.0m; default: throw new ArgumentException(...); } }
Endbeispiel
Ein var_pattern entspricht jedem Wert. Das heißt, ein Musterabgleichsvorgang mit einem var_pattern ist immer erfolgreich.
Ein var_pattern gilt für jeden Typ.
var_pattern
: 'var' designation
;
designation
: simple_designation
;
Bei einem Mustereingabewert (§11.1) e, wenn die Bezeichnung der Bezeichner _
ist, wird ein Verwerfen (§9.2.9.1) bezeichnet, und der Wert von e ist an nichts gebunden. (Obwohl eine deklarierte Variable mit diesem Namen zu diesem Zeitpunkt im Bereich enthalten sein kann, wird diese benannte Variable in diesem Kontext nicht angezeigt.) Wenn die Bezeichnung ein anderer Bezeichner ist, ist der Wert von e zur Laufzeit an eine neu eingeführte lokale Variable (§9.2.9) dieses Namens gebunden, deren Typ der statische Typ von e ist, und der Mustereingabewert dieser lokalen Variablen zugewiesen wird.
Es ist ein Fehler, wenn der Name var
an einen Typ gebunden würde, in dem ein var_pattern verwendet wird.
Bei einer Switch-Anweisung handelt es sich um einen Fehler, wenn das Muster eines Falls von der vorherigen Gruppe nicht überwachter Fälle (§13.8.3) subsumiert wird. Informell bedeutet dies, dass jeder Eingabewert mit einem der vorherigen Fälle abgeglichen worden wäre. Die folgenden Regeln definieren, wann eine Reihe von Mustern ein bestimmtes Muster subsumiert:
Ein Muster P
stimmt mit einer Konstante K
überein, wenn die Spezifikation für das Laufzeitverhalten P
dieses Musters mit übereinstimmungtK
.
Eine Reihe von Mustern Q
subsumiert ein Muster P
, wenn eine der folgenden Bedingungen enthalten ist:
P
ist ein konstantes Muster, und jedes der Muster in der Gruppe Q
würde mit dem konvertierten Wert übereinstimmenP
.P
ist ein Var-Muster, und der Satz von Mustern Q
ist erschöpfend (§11.4) für den Typ des Mustereingabewerts (§11.1), und entweder ist der Mustereingabewert kein nullabler Typ oder ein Muster Q
in übereinstimmungen.null
P
ist ein Deklarationsmuster mit Typ T
und der Satz von Mustern Q
ist für den Typ T
erschöpfend (§11.4).Informell ist eine Reihe von Mustern für einen Typ erschöpfend, wenn für jeden möglichen Wert dieses Typs außer NULL ein bestimmtes Muster in der Menge anwendbar ist. Die folgenden Regeln definieren, wann eine Reihe von Mustern für einen Typ erschöpfend ist:
Eine Reihe von Mustern Q
ist für einen Typ T
erschöpfend, wenn eine der folgenden Bedingungen enthalten ist:
T
ist ein integraler oder enumerationstyp oder eine nullable Version einer dieser Typen, und für jeden möglichen Wert des T
nicht nullablen zugrunde liegenden Typs würde ein Muster Q
mit diesem Wert übereinstimmen; oderQ
ein Var-Muster; oderQ
handelt es sich um ein Deklarationsmuster für den Typ D
, und es gibt eine Identitätskonvertierung, eine implizite Verweiskonvertierung oder eine Boxumwandlung von T
zu D
.Beispiel:
C#
static void M(byte b) { switch (b) { case 0: case 1: case 2: ... // handle every specific value of byte break; // error: the pattern 'byte other' is subsumed by the (exhaustive) // previous cases case byte other: break; } }
Endbeispiel
Feedback zu ECMA C# draft specification
ECMA C# draft specification ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Ereignisse
17. März, 23 Uhr - 21. März, 23 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrieren