Partage via


Modèles de liste

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 .

Problème de champion : https://github.com/dotnet/csharplang/issues/3435

Résumé

Vous permet de faire correspondre un tableau ou une liste avec une séquence de modèles, par exemple, array is [1, 2, 3] correspondra à un tableau entier de la longueur 3 avec 1, 2, 3 comme éléments, respectivement.

Conception détaillée

La syntaxe du modèle est modifiée comme suit :

list_pattern_clause
  : '[' (pattern (',' pattern)* ','?)? ']'
  ;

list_pattern
  : list_pattern_clause simple_designation?
  ;

slice_pattern
  : '..' pattern?
  ;

primary_pattern
  : list_pattern
  | slice_pattern
  | // all of the pattern forms previously defined
  ;

Il existe deux nouveaux modèles :

  • La list_pattern est utilisée pour faire correspondre les éléments.
  • Un slice_pattern n’est autorisé qu’une seule fois et uniquement directement dans une list_pattern_clause et ignore zéro ou plusieurs éléments.

Compatibilité des modèles

Un list_pattern est compatible avec tout type qui est dénombrable et indexable ; il dispose d'un indexeur accessible qui prend un Index en tant qu'argument ou un indexeur accessible avec un seul paramètre int. Si les deux indexeurs sont présents, l’ancien est préféré.

Un slice_pattern avec un sous-modèle est compatible avec n’importe quel type dénombrable, ainsi que segmentable, il a un index accessible qui prend un Range en tant qu’argument ou une méthode Slice accessible avec deux paramètres int. Si les deux sont présents, l’ancien est préféré.

Un slice_pattern sans sous-motif est compatible avec tout type compatible avec un list_pattern.

Cet ensemble de règles est dérivé du modèle d’indexeur de plage .

Vérification de la subsomption

La vérification de la subsomption fonctionne comme les modèles positionnels avec ITuple : les sous-modèles correspondants sont mis en correspondance par position et un nœud supplémentaire pour la longueur de test.

Par exemple, le code suivant génère une erreur, car les deux modèles produisent le même DAG :

case [_, .., 1]: // expr.Length is >= 2 && expr[^1] is 1
case [.., _, 1]: // expr.Length is >= 2 && expr[^1] is 1

Contrairement à :

case [_, 1, ..]: // expr.Length is >= 2 && expr[1] is 1
case [.., 1, _]: // expr.Length is >= 2 && expr[^2] is 1

L’ordre dans lequel les sous-modèles sont mis en correspondance au moment de l’exécution n’est pas spécifié, et une correspondance ayant échoué peut ne pas tenter de faire correspondre tous les sous-modèles.

Compte tenu d’une longueur spécifique, il est possible que deux sous-segments font référence au même élément, auquel cas un test de cette valeur est inséré dans le DAG de décision.

  • Par exemple, [_, >0, ..] or [.., <=0, _] devient length >= 2 && ([1] > 0 || length == 3 || [^2] <= 0) où la valeur de longueur de 3 implique l’autre test.
  • À l’inverse, [_, >0, ..] and [.., <=0, _] devient length >= 2 && [1] > 0 && length != 3 && [^2] <= 0 où la valeur de longueur de 3 interdit l’autre test.

Par conséquent, une erreur est générée pour quelque chose comme case [.., p]: case [p]:, car au moment de l’exécution, nous mettons en correspondance le même élément dans le deuxième cas.

Si un sous-modèle de segment correspond à une liste ou à une valeur de longueur, les sous-modèles sont traités comme s’ils étaient un sous-modèle direct de la liste contenante. Par exemple, [..[1, 2, 3]] subsume un modèle de la forme [1, 2, 3].

Les hypothèses suivantes sont faites sur les membres utilisés :

  • La propriété qui rend le type countable est supposée toujours retourner une valeur non négative, si et seulement si le type est indexable. Par exemple, le modèle { Length: -1 } ne peut jamais correspondre à un tableau.
  • Le membre qui rend le type segmentable est supposé avoir un bon comportement, autrement dit, la valeur de retour n’est jamais nulle et constitue une sous-tranche appropriée de la liste contenante.

Le comportement d’une opération de correspondance de modèle n’est pas défini si l’une des hypothèses ci-dessus ne tient pas.

Abaissement

Un modèle de formulaire expr is [1, 2, 3] équivaut au code suivant :

expr.Length is 3
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Index(1, fromEnd: false)] is 2
&& expr[new Index(2, fromEnd: false)] is 3

Un slice_pattern fonctionne comme un filtre adéquat, c’est-à-dire qu’aucun test ne sera émis pour ce modèle, mais il affecte uniquement d’autres nœuds, à savoir la longueur et l’indexeur. Par exemple, un modèle de la forme expr is [1, .. var s, 3] équivaut au code suivant (si compatible via un support explicite de Index et de Range) :

expr.Length is >= 2
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))] is var s
&& expr[new Index(1, fromEnd: true)] is 3

Le type d'entrée pour le slice_pattern est le type de retour de la méthode sous-jacente this[Range] ou Slice, avec deux exceptions : pour string et des tableaux, string.Substring et RuntimeHelpers.GetSubArray seront utilisés, respectivement.

Questions non résolues

  1. Devons-nous prendre en charge des tableaux multidimensionnels ? (réponse [LDM 2021-05-26] : Non pris en charge. Si nous voulons faire une version générale axée sur MD-array, nous devrions revoir tous les domaines actuellement manquants, pas seulement les modèles de liste.)
  2. Devrions-nous accepter un modèle général suivant .. dans un schéma de découpe ? (réponse [LDM 2021-05-26] : Oui, tout modèle est autorisé après une tranche.)
  3. Par cette définition, le modèle [..] teste pour expr.Length >= 0. Devrions-nous omettre ce test, en supposant que Length est toujours non négatif ? (réponse [LDM 2021-05-26] : [..] n’émettra pas de vérification de longueur)