Сопоставление шаблонов Span<char>
в постоянной строке
Заметка
Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Она включает предлагаемые изменения спецификации, а также информацию, необходимую во время дизайна и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.
Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия зафиксированы в соответствующих заметках собраний по проектированию языка (LDM).
Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .
Сводка
Разрешить совпадение шаблона для Span<char>
и ReadOnlySpan<char>
в константной строке.
Мотивация
Для производительности использование Span<char>
и ReadOnlySpan<char>
предпочтительнее по сравнению со строкой во многих сценариях. Платформа добавила множество новых API, которые позволяют использовать ReadOnlySpan<char>
вместо string
.
Распространенная операция со строками заключается в использовании переключателя для проверки того, является ли это определенное значение, и компилятор оптимизирует такой коммутатор. Однако в настоящее время нет возможности сделать то же самое на ReadOnlySpan<char>
эффективно, кроме как путем ручной реализации переключения и оптимизации.
Чтобы поощрять внедрение ReadOnlySpan<char>
, мы разрешаем сопоставление шаблонов ReadOnlySpan<char>
на константном string
, что также позволяет использовать его в коммутаторе.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Подробный дизайн
Мы изменим спецификации для постоянных шаблонов следующим образом (предлагаемое добавление отображается полужирным шрифтом):
Учитывая входное значение шаблона
e
и константный шаблонP
с преобразованным значениемv
.
- Если e имеет целочисленный тип или тип перечисления, или пустую форму одного из них, а v имеет целочисленный тип, шаблон
P
соответствует значению e, если результат выраженияe == v
равенtrue
; иначе- Если e имеет тип
System.Span<char>
илиSystem.ReadOnlySpan<char>
, а c является константной строкой, а c не имеет константного значенияnull
, то шаблон считается совпадающим, еслиSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
возвращаетtrue
.- Шаблон
P
соответствует значению e, еслиobject.Equals(e, v)
возвращаетtrue
.
Известные члены
System.Span<T>
и System.ReadOnlySpan<T>
совпадают по имени, должны быть ref struct
и могут быть определены вне corelib.
System.MemoryExtensions
совпадает по имени и может быть определён вне corelib.
Сигнатура перегрузки System.MemoryExtensions.SequenceEqual
должна соответствовать.
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
Подпись System.MemoryExtensions.AsSpan
должна соответствовать:
public static System.ReadOnlySpan<char> AsSpan(string)
Методы с необязательными параметрами исключаются из рассмотрения.
Недостатки
Никакой
Альтернативы
Никакой
Неразрешенные вопросы
Следует ли задавать сопоставление независимо от
MemoryExtensions.SequenceEqual()
и т. д.?... Шаблон считается соответствующим, если
e.Length == c.Length
иe[i] == c[i]
для всех символов вe
.Рекомендация: Определите в терминах
MemoryExtensions.SequenceEqual()
для повышения производительности. ЕслиMemoryExtensions
отсутствует, сообщите об ошибке компиляции.Разрешить ли соответствие с
(string)null
?Если да, следует ли
(string)null
подчинить""
, так какMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
Рекомендация : о шаблоне
(string)null
следует сообщать как об ошибке.Следует ли включать проверку типа во время выполнения для значений выражения
Span<char>
илиReadOnlySpan<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? }
Рекомендация. Неявный тест типа среды выполнения для постоянного шаблона. (
IsABC<T>()
разрешено в примере, так как тест типа является явным.)Эта рекомендация не реализована. Все предыдущие примеры создают ошибку компилятора.
Должно ли подведение учитывать шаблоны строковых констант, шаблоны списков и шаблон свойства
Length
?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
Рекомендация: Использовать такое же поведение подстановки, как при значении выражения
string
. (Это означает, что между константными строками, шаблонами списков иLength
нет отношений подстановки, кроме случая, когда[..]
рассматривается как совпадающий с любым?)
Встречи по дизайну
C# feature specifications