Dopasowanie wzorca Span<char>
na ciągu stałym
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Streszczenie
Zezwalaj na dopasowywanie wzorca Span<char>
i ReadOnlySpan<char>
w ciągu stałym.
Motywacja
Ze względu na wydajność, w wielu scenariuszach preferowane jest używanie Span<char>
i ReadOnlySpan<char>
zamiast ciągów. Aby umożliwić korzystanie z ReadOnlySpan<char>
zamiast string
, platforma dodała wiele nowych interfejsów API.
Typową operacją na ciągach jest użycie przełącznika do testowania, czy jest to określona wartość, a kompilator optymalizuje taki przełącznik. Jednak obecnie nie ma możliwości wykonania tego samego na ReadOnlySpan<char>
w sposób wydajny, poza ręczną implementacją przełącznika i optymalizacją.
Aby zachęcić do przyjęcia ReadOnlySpan<char>
zezwalamy na dopasowywanie wzorca ReadOnlySpan<char>
na stałym string
, co pozwala również na jego użycie w przełączniku.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Szczegółowy projekt
Zmieniamy spec dla stałych wzorców w sposób następujący (proponowany dodatek jest wyświetlany pogrubioną czcionką):
Biorąc pod uwagę wartość wejściową wzorca
e
i stały wzorzecP
z przekonwertowaną wartościąv
,
- jeśli e ma typ całkowity lub typ wyliczeniowy albo formę dopuszczaną do wartości null jednego z nich, a v ma typ całkowity, wzorzec
P
pasuje wartości e, jeśli wynik wyrażeniae == v
jesttrue
; inaczej- Jeśli e jest typu
System.Span<char>
lubSystem.ReadOnlySpan<char>
, a c jest ciągiem stałym, a c nie ma stałej wartościnull
, wzorzec jest traktowany jako zgodny, jeśliSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
zwracatrue
.- wzorzec
P
pasuje wartości e, jeśliobject.Equals(e, v)
zwraca wartośćtrue
.
Dobrze znani członkowie
System.Span<T>
i System.ReadOnlySpan<T>
są dopasowywane według nazwy, muszą być ref struct
s i można je zdefiniować poza corlibem.
System.MemoryExtensions
pasuje do nazwy i można go zdefiniować poza corlib.
Podpis przeciążeń System.MemoryExtensions.SequenceEqual
musi być zgodny z następującymi elementami:
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
Podpis System.MemoryExtensions.AsSpan
musi być zgodny z następującymi elementami:
public static System.ReadOnlySpan<char> AsSpan(string)
Metody z opcjonalnymi parametrami są wykluczone z uwagi.
Minusy
Żaden
Alternatywy
Żaden
Nierozwiązane pytania
Czy dopasowanie powinno być definiowane niezależnie od
MemoryExtensions.SequenceEqual()
itp.?... wzorzec jest uznawany za zgodny, jeśli
e.Length == c.Length
ie[i] == c[i]
są takie same dla wszystkich znaków we
.Zalecenie: zdefiniuj
MemoryExtensions.SequenceEqual()
dla wydajności. Jeśli brakujeMemoryExtensions
, zgłoś błąd kompilacji.Czy dopuszczalne jest dopasowanie do
(string)null
?Jeśli tak, czy
(string)null
podsumować""
odMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
Zalecenie: wzorzec stały
(string)null
powinien być zgłaszany jako błąd.Czy wzorzec stały powinien zawierać test typu środowiska uruchomieniowego wartości wyrażenia dla
Span<char>
lubReadOnlySpan<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? }
Zalecenie: brak niejawnego testu typu środowiska uruchomieniowego dla wzorca stałego. (
IsABC<T>()
przykład jest dozwolony, ponieważ test typu jest jawny.To zalecenie nie zostało zaimplementowane. Wszystkie powyższe przykłady generują błąd kompilatora.
Czy subsumcja powinna uwzględniać stałe wzorce ciągów, wzorce list i wzorzec właściwości
Length
?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
Zalecenie: To samo zachowanie subsumcji, które jest stosowane, gdy wartość wyrażenia wynosi
string
. (Czy to oznacza brak podsumpcji między ciągami stałymi, wzorcami listy iLength
, oprócz traktowania[..]
jako dopasowujący się do wszystkich?)
Spotkania projektowe
C# feature specifications