Musterübereinstimmung Span<char>
auf eine konstante Zeichenkette
Anmerkung
Dieser Artikel ist eine Featurespezifikation. Die Spezifikation dient als Designdokument für das Feature. Es enthält vorgeschlagene Spezifikationsänderungen sowie Informationen, die während des Entwurfs und der Entwicklung des Features erforderlich sind. Diese Artikel werden veröffentlicht, bis die vorgeschlagenen Spezifikationsänderungen abgeschlossen und in die aktuelle ECMA-Spezifikation aufgenommen werden.
Es kann einige Abweichungen zwischen der Featurespezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede sind in den einschlägigen Notizen zum Sprachdesign-Meeting (LDM).
Weitere Informationen über den Prozess zur Aufnahme von Feature Speclets in den C#-Sprachstandard finden Sie in dem Artikel über die Spezifikationen.
Zusammenfassung
Erlauben Sie den Mustervergleich einer Span<char>
und eine ReadOnlySpan<char>
auf eine konstante Zeichenfolge.
Motivation
Für die Leistung, die Verwendung von Span<char>
und ReadOnlySpan<char>
wird in vielen Szenarien gegenüber String bevorzugt. Das Framework hat viele neue APIs hinzugefügt, mit denen Sie ReadOnlySpan<char>
anstelle einer string
verwenden können.
Ein gängiger Vorgang für Zeichenfolgen besteht darin, einen Switch zu verwenden, um zu testen, ob es sich um einen bestimmten Wert handelt, und der Compiler optimiert einen solchen Schalter. Allerdings gibt es derzeit keine Möglichkeit, dasselbe auf einer ReadOnlySpan<char>
effizienter zu gestalten, als den Wechsel und die Optimierung manuell durchzuführen.
Zur Förderung der Einführung von ReadOnlySpan<char>
erlauben wir einen Mustervergleich ReadOnlySpan<char>
, mit einer Konstante string
, und kann somit auch in einem Schalter verwendet werden.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Detailliertes Design
Wir ändern die -Spezifikation für Konstantenmuster wie folgt, wobei die vorgeschlagene Ergänzung fett hervorgehoben ist.
Angesichts eines Mustereingabewerts
e
und ein konstantes MusterP
mit umgerechnetem Wertv
,
- wenn e einen Integral- oder Enum-Typ oder eine nullbare Form eines dieser Typen hat und v hat einen integralen Typ, das Muster
P
passt zu der Wert e wenn das Ergebnis des Ausdruckse == v
istrue
; ansonsten- Wenn e vom Typ
System.Span<char>
oderSystem.ReadOnlySpan<char>
ist und c eine konstante Zeichenfolge ist und c keinen konstanten Wert vonnull
aufweist, wird das Muster als übereinstimmend betrachtet, wennSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
true
zurückgibt.- das Muster
P
passt zu der Wert e wennobject.Equals(e, v)
gibt zurücktrue
.
Bekannte Mitglieder
System.Span<T>
und System.ReadOnlySpan<T>
mit dem Namen übereinstimmen, müssen ref struct
s, und kann außerhalb von corlib definiert werden.
System.MemoryExtensions
wird nach Namen abgeglichen und kann außerhalb von corlib definiert werden.
Die Unterschrift von System.MemoryExtensions.SequenceEqual
Überlastungen müssen übereinstimmen:
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
Die Unterschrift von System.MemoryExtensions.AsSpan
müssen übereinstimmen:
public static System.ReadOnlySpan<char> AsSpan(string)
Methoden mit optionalen Parametern werden von der Berücksichtigung ausgeschlossen.
Nachteile
Nichts
Alternativen
Nichts
Ungelöste Fragen
Sollte die Übereinstimmung unabhängig von
MemoryExtensions.SequenceEqual()
usw.?... wird das Muster als übereinstimmend angesehen, wenn
e.Length == c.Length
unde[i] == c[i]
für alle Zeichen ine
.Empfehlung: Definieren Sie im Sinne von
MemoryExtensions.SequenceEqual()
für Leistung. WennMemoryExtensions
fehlt, melden Sie den Kompilierungsfehler.Sollte der Abgleich mit
(string)null
erlaubt sein?Wenn ja, sollte
(string)null
fassen""
seitMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
Empfehlung: Konstantes Muster
(string)null
sollte als Fehler gemeldet werden.Sollte die Konstantenmusterübereinstimmung einen Laufzeittyptest des Ausdruckswerts für
Span<char>
oderReadOnlySpan<char>
?static bool Is123<T>(Span<T> s) { return s is "123"; // test for Span<char>? } static bool IsABC<T>(Span<T> s) { return s is Span<char> and "ABC"; // ok? } static bool IsEmptyString<T>(T t) where T : ref struct { return t is ""; // test for ReadOnlySpan<char>, Span<char>, string? }
Empfehlung: Kein impliziter Laufzeittyptest für konstanten Muster. (
IsABC<T>()
Beispiel ist erlaubt, weil der Typentest explizit ist).Diese Empfehlung wurde nicht implementiert. Alle vorherigen Beispiele erzeugen einen Compilerfehler.
Sollte die Subsumtion konstante Zeichenfolgenmuster, Listenmuster und
Length
Eigenschaftsmuster?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
Empfehlung: Gleiches Subsumtionsverhalten wie bei der Verwendung des Ausdruckswerts
string
. (Bedeutet das, dass keine Subsumtion zwischen konstanten Zeichenketten, Listenmustern undLength
, andere als die Behandlung[..]
als übereinstimmend mit jeder?)
Entwurfsbesprechungen
C# feature specifications