Correspondance de modèle d’une Span<char>
sur une chaîne constante
Remarque
Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Il inclut les modifications de spécification proposées, ainsi que les informations nécessaires pendant la conception et le développement de la fonctionnalité. Ces articles sont publiés jusqu’à ce que les modifications de spécification proposées soient finalisées et incorporées dans la spécification ECMA actuelle.
Il peut y avoir des différences entre la spécification de la fonctionnalité et l’implémentation terminée. Ces différences sont consignées dans les notes pertinentes de la réunion de conception linguistique (LDM).
Vous pouvez en savoir plus sur le processus d’adoption des speclets de fonctionnalités dans la norme de langage C# dans l’article sur les spécifications .
Résumé
Permettre la correspondance de modèle d’une Span<char>
et d’une ReadOnlySpan<char>
dans une chaîne constante.
Motivation
Pour la performance, l’utilisation de Span<char>
et de ReadOnlySpan<char>
est préférée à la chaîne de caractères dans de nombreux scénarios. Le framework a ajouté de nombreuses nouvelles API pour vous permettre d’utiliser ReadOnlySpan<char>
à la place d’un string
.
Une opération courante sur les chaînes consiste à utiliser un commutateur pour tester s’il s’agit d’une valeur particulière, et le compilateur optimise ce commutateur. Toutefois, il n’existe actuellement aucun moyen de procéder de la même façon sur un ReadOnlySpan<char>
efficacement, à part l’implémentation du commutateur et de l’optimisation manuellement.
Afin d’encourager l’adoption de ReadOnlySpan<char>
, nous permettons la correspondance de modèle d’une ReadOnlySpan<char>
sur une constante string
, ce qui permet également son utilisation dans une instruction switch.
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
Conception détaillée
Nous modifions la spécification pour les modèles constants comme suit (l’ajout proposé est présenté en gras) :
Étant donné une valeur d’entrée de modèle
e
et un modèle constantP
avec une valeur convertiev
,
- si e possède un type intégral ou un type d’énumération, ou une forme autorisant une valeur nulle de l’un de ces types et v possède un type intégral, le modèle
P
correspond à la valeur e si le résultat de l’expressione == v
esttrue
; autrement- Si e est de type
System.Span<char>
ouSystem.ReadOnlySpan<char>
, et c est une chaîne constante, et c n’a pas de valeur constante denull
, le modèle est considéré comme correspondant siSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
retournetrue
.- le modèle
P
correspond à la valeur e siobject.Equals(e, v)
retournetrue
.
Membres connus
System.Span<T>
et System.ReadOnlySpan<T>
sont mis en correspondance par nom, doivent être ref struct
s et peuvent être définis en dehors du corlib.
System.MemoryExtensions
est associé par nom et peut être défini en dehors de corlib.
La signature des surcharges de System.MemoryExtensions.SequenceEqual
doit correspondre à :
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
La signature de System.MemoryExtensions.AsSpan
doit correspondre à :
public static System.ReadOnlySpan<char> AsSpan(string)
Les méthodes avec des paramètres facultatifs sont exclues de la considération.
Inconvénients
Aucun
Alternatives
Aucun
Questions non résolues
La correspondance doit-elle être définie indépendamment de
MemoryExtensions.SequenceEqual()
etc. ?... le modèle est considéré comme correspondant si
e.Length == c.Length
ete[i] == c[i]
pour tous les caractères dee
.Recommandation : Définir en termes de
MemoryExtensions.SequenceEqual()
pour les performances. SiMemoryExtensions
est manquant, signalez l’erreur de compilation.La mise en correspondance par rapport à
(string)null
doit-elle être autorisée ?Si c’est le cas,
(string)null
devrait-il englober""
étant donnéMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
Recommandation : le modèle constant
(string)null
doit être signalé comme une erreur.La correspondance du modèle constant doit-elle inclure un test de type runtime de la valeur d’expression pour
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? }
Recommandation : aucun test de type d’exécution implicite pour le modèle constant. (L'exemple
IsABC<T>()
est autorisé, car le test de type est explicite.)Cette recommandation n’a pas été mise en œuvre. Tous les exemples précédents produisent une erreur du compilateur.
La subsomption doit-elle prendre en compte les modèles de chaînes constantes, les modèles de liste et le modèle de propriété
Length
?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
Recommandation : même comportement de soussomption que celui utilisé lorsque la valeur de l'expression est
string
. (Cela signifie-t-il qu'il n'y a pas de subsomption entre les chaînes constantes, les modèles de liste etLength
, à l'exception de traiter[..]
comme une correspondance à n'importe quoi ?)
Concevoir des réunions
C# feature specifications