Coincidencia de patrones de Span<char>
en una cadena de constante
Nota
Este artículo es una especificación de características. La especificación actúa como documento de diseño de la característica. Incluye cambios de especificación propuestos, junto con la información necesaria durante el diseño y el desarrollo de la característica. Estos artículos se publican hasta que se finalizan los cambios de especificación propuestos e se incorporan en la especificación ECMA actual.
Puede haber algunas discrepancias entre la especificación de características y la implementación completada. Esas diferencias se recogen en las notas de la reunión de diseño de lenguaje (LDM) correspondientes.
Puede obtener más información sobre el proceso de adopción de especificaciones de características en el estándar del lenguaje C# en el artículo sobre las especificaciones de .
Resumen
Permitir la coincidencia de un patrón Span<char>
y un ReadOnlySpan<char>
en una cadena constante.
Motivación
Para el rendimiento, se prefiere el uso de Span<char>
y ReadOnlySpan<char>
sobre la cadena de caracteres en muchos escenarios. El marco ha agregado muchas API nuevas para permitirle usar ReadOnlySpan<char>
en lugar de un string
.
Una operación común en cadenas es usar un modificador para probar si es un valor determinado y el compilador optimiza dicho modificador. Sin embargo, actualmente no hay ninguna manera de hacer lo mismo en una ReadOnlySpan<char>
eficazmente, aparte de implementar el conmutador y la optimización manualmente.
Para fomentar la adopción de ReadOnlySpan<char>
permitimos que el patrón coincida con un ReadOnlySpan<char>
, en una constante string
, lo que también permite su uso en un conmutador.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Diseño detallado
Modificamos la especificación de para patrones constantes como se indica a continuación (la adición propuesta se muestra en negrita):
Dado un valor de patrón de entrada
e
y un patrón constanteP
, cuyo valor convertido esv
,
- si e tiene tipo entero o tipo de enumeración, o una forma que acepta valores NULL de uno de ellos y v tiene un tipo entero, el patrón
P
coincide con el valor e si el resultado de la expresióne == v
estrue
; de otra manera- Si e es de tipo
System.Span<char>
oSystem.ReadOnlySpan<char>
, y c es una cadena constante y c no tiene un valor constante denull
, el patrón se considera coincidente siSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
devuelvetrue
.- el patrón
P
coincide con el valor e siobject.Equals(e, v)
devuelvetrue
.
Miembros conocidos
System.Span<T>
y System.ReadOnlySpan<T>
coinciden por nombre, deben ser ref struct
s y se pueden definir fuera de corlib.
System.MemoryExtensions
coincide con el nombre y se puede definir fuera de corlib.
La firma de las sobrecargas de System.MemoryExtensions.SequenceEqual
debe coincidir con:
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
La firma de System.MemoryExtensions.AsSpan
debe coincidir con:
public static System.ReadOnlySpan<char> AsSpan(string)
Los métodos con parámetros opcionales se excluyen de la consideración.
Inconvenientes
Ninguno
Alternativas
Ninguno
Preguntas sin resolver
¿Debe definirse la coincidencia independientemente de
MemoryExtensions.SequenceEqual()
etc.?... el patrón se considera coincidente si
e.Length == c.Length
ye[i] == c[i]
para todos los caracteres dee
.Recomendación: defina en términos de
MemoryExtensions.SequenceEqual()
para el rendimiento. Si faltaMemoryExtensions
, notifique el error de compilación.¿Se debe permitir la coincidencia con
(string)null
?Si es así, ¿debe
(string)null
subsumir a""
ya queMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
Recomendación: el patrón constante
(string)null
debe notificarse como un error.¿Debe la coincidencia de patrones constantes incluir una prueba de tipo en tiempo de ejecución del valor de expresión para
Span<char>
oReadOnlySpan<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? }
Recomendación: no hay pruebas implícitas de tipo en tiempo de ejecución para el patrón constante. (El ejemplo
IsABC<T>()
se permite porque la prueba de tipo es explícita).Esta recomendación no se implementó. Todos los ejemplos anteriores producen un error del compilador.
¿Debe la subsumpción considerar los patrones de cadena constantes, los patrones de lista y el patrón de propiedad
Length
?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
Recomendación: usar el mismo comportamiento de subsunción que se emplea cuando el valor de la expresión es
string
. (¿Esto significa que no hay subsumición entre cadenas constantes, patrones de lista yLength
, aparte de tratar[..]
como que coincide con cualquiera?)
Reuniones de diseño
C# feature specifications