Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Coincidencia de patrones de
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 y 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 especificaciones.
Problema planteado por el experto: https://github.com/dotnet/csharplang/issues/8640
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 añadido muchas API nuevas para permitirte usar ReadOnlySpan<char>
en lugar de un string
.
Una operación común en cadenas es utilizar un conmutador para comprobar si es un valor determinado, y el compilador optimiza dicho conmutador. Sin embargo, actualmente no hay manera de hacer lo mismo en un ReadOnlySpan<char>
de manera eficiente, aparte de implementar el interruptor 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 spec para patrones constantes de la siguiente manera (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
, entonces 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
, y pueden definirse 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:
public static System.ReadOnlySpan<char> AsSpan(string)
Los métodos con parámetros opcionales se excluyen de la consideración.
Inconvenientes
Ninguna
Alternativas
Ninguna
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
, informe de 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
debería notificarse como 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 prueba de tipo implícita 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 ha implementado. Todos los ejemplos anteriores producen un error de 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