Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Correspondência de padrões de
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ela inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas divergências entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da reunião de design de idioma (LDM).
Você pode saber mais sobre o processo de adoção de speclets de recursos no padrão de linguagem C# no artigo sobre as especificações de .
Problema do especialista: https://github.com/dotnet/csharplang/issues/8640
Resumo
Permitir a correspondência de padrões de Span<char> e ReadOnlySpan<char> em uma cadeia de caracteres constante.
Motivação
Para fins de desempenho, o uso de Span<char> e ReadOnlySpan<char> é preferido em vez de cadeias de caracteres em muitos cenários. A estrutura adicionou muitas APIs novas para permitir que você use ReadOnlySpan<char> no lugar de um string.
Uma operação comum em strings é usar um switch para testar se é um valor específico, e o compilador otimiza esse switch. No entanto, atualmente, não há como fazer o mesmo em um ReadOnlySpan<char> com eficiência, além de implementar a opção e a otimização manualmente.
Para incentivar a adoção do ReadOnlySpan<char>, permitimos a correspondência de padrões de um ReadOnlySpan<char>, em um stringconstante, permitindo assim que também seja utilizado em uma troca.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Projeto detalhado
Alteramos a especificação para padrões constantes da seguinte maneira (a adição proposta é mostrada em negrito):
Dado um valor de entrada padrão
ee um padrão constantePcom valor convertidov,
- se e tiver tipo integral ou tipo de enumeração, ou uma forma anulável de um desses, e v tiver tipo integral, o padrão
Pcorresponderá ao valor e se o resultado da expressãoe == vfortrue; caso contrário- Se e for do tipo
System.Span<char>ouSystem.ReadOnlySpan<char>e c for uma cadeia de caracteres constante e c não tiver um valor constante denull, o padrão será considerado correspondente seSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))retornartrue.- o padrão
Pcorresponderá ao valor e seobject.Equals(e, v)retornartrue.
Membros conhecidos
System.Span<T> e System.ReadOnlySpan<T> são correspondidos por nomes; devem ser ref structs e podem ser definidos fora do corlib.
System.MemoryExtensions é correspondido pelo nome e pode ser definido fora do corlib.
A assinatura de sobrecargas de System.MemoryExtensions.SequenceEqual deve corresponder:
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
A assinatura de System.MemoryExtensions.AsSpan deve corresponder:
public static System.ReadOnlySpan<char> AsSpan(string)
Métodos com parâmetros opcionais são excluídos da consideração.
Desvantagens
Nenhum
Alternativas
Nenhum
Perguntas não resolvidas
A correspondência deve ser definida independentemente de
MemoryExtensions.SequenceEqual()etc.?... o padrão é considerado uma correspondência se
e.Length == c.Lengthee[i] == c[i]forem iguais para todos os caracteres eme.Recomendação: definir em termos de
MemoryExtensions.SequenceEqual()para desempenho. SeMemoryExtensionsestiver ausente, relate o erro de compilação.A correspondência com
(string)nulldeve ser permitida?Se sim,
(string)nulldeve se subordinar a"", visto queMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }Recomendação: um padrão constante
(string)nulldeve ser reportado como um erro.A correspondência constante de padrões deve incluir um teste de tipo de runtime do valor da expressão para
Span<char>ouReadOnlySpan<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? }Recomendação: nenhum teste de tipo de runtime implícito para padrão constante. (
IsABC<T>()exemplo é permitido porque o teste de tipo é explícito.)Esta recomendação não foi implementada. Todos os exemplos anteriores produzem um erro de compilador.
A subordinação deve considerar padrões de cadeia de caracteres constantes, padrões de listas e padrões de propriedade
Length?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }Recomendação: mesmo comportamento de subsunção usado quando o valor da expressão é
string. (Isso significa que não há subordinação entre cadeias de caracteres constantes, padrões de lista eLength, além de tratar[..]como correspondentes a qualquer um?)
Reuniões de design
C# feature specifications