C # 7.0 introduit la notion de patterns (modèles) que Microsoft décrit comme étant des éléments syntaxiques qui peuvent vérifier qu'une valeur a un certain « motif » et en extraire des informations une fois que la vérification est faite. Le filtrage par motif (pattern matching) permet de vérifier si l'objet du filtrage possède une structure donnée, s'il s'y trouve telle ou telle sous-structure spécifique et/ou éventuellement pour substituer quelque chose d'autre aux motifs reconnus. Comme exemple de filtres dans C # 7.0, Microsoft évoque :
- les filtres constants de la forme c (où c est une expression constante dans C #), qui servent à vérifier que l’entrée est égale à c ;
- les filtres de type T x (où T est un type et x un identifiant), qui servent à vérifier qu’une entrée est bien du type T et, si c’est le cas, extraire la valeur de l’entrée dans une nouvelle variable x de type T ;
- les filtres de la forme var x (où x est un identifiant), qui effectuent toujours des correspondances et mettent simplement la valeur de l'entrée dans une variable x du même type que l'entrée.
Voici un exemple avec un filtre constant et un filtre de type
Code C# : | Sélectionner tout |
1 2 3 4 5 6 | public void PrintStars(object o) { if (o is null) return; // filtre constant "null" if (!(o is int i)) return; // filtre de type "int i" WriteLine(new string('*', i)); } |
Microsoft explique que les filtrages par motifs et les structures de contrôles vont souvent bien ensemble. Raison pour laquelle par exemple dans les instructions switch, qui permettent de tester plusieurs valeurs pour une expression, Microsoft a apporté des changements :
- pour permettre d’effectuer un switch sur n’importe quel type (qui se limitait jusqu’à présent aux expressions de type scalaire comme les entiers, les caractères, les énumérations ou les booléens) ;
- pour permettre d’utiliser des filtres dans les déclarations de série d’instructions (case) ;
- pour permettre l’ajout de conditions additionnelles sur les clauses case.
Voici un simple exemple :
Code C# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | switch(shape) { case Circle c: WriteLine($"circle with radius {c.Radius}"); break; case Rectangle s when (s.Length == s.Height): WriteLine($"{s.Length} x {s.Height} square"); break; case Rectangle r: WriteLine($"{r.Length} x {r.Height} rectangle"); break; default: WriteLine("<unknown shape>"); break; case null: throw new ArgumentNullException(nameof(shape)); } |
Microsoft apporte toutefois quelques précisions suite à l’extension de la structure de contrôle switch. Désormais, l’ordre des clauses case importe désormais, comme dans les clauses catch, étant donné que ces clauses ne sont plus nécessairement disjointes. De plus, comme dans les clauses catch, le compilateur va vous aider à repérer des cas évidents qui ne seront jamais atteints. La clause par défaut est toujours évaluée en dernier : dans l’exemple ci-dessus, bien que la clause « null » vienne en dernier, elle sera évaluée avant la clause par défaut.
Les tuples, qui facilitent la possibilité de retourner plusieurs résultats, sont également annoncés comme étant l’un des changements les plus significatifs apportés avec cette version. Notons qu’avant la venue des tuples, il était possible de retourner plusieurs résultats. Cependant, les options n’étaient pas optimales. C# 7.0 proposent aux développeurs de se servir des littéraux et des types.
Code C# : | Sélectionner tout |
1 2 3 4 5 | (string, string, string) LookupName(long id) // tuple return type { ... // va retirer first, middle et last from du stockage de données return (first, middle, last); // littéral du tuple } |
Cette méthode retourne trois chaînes de caractères encapsulées dans un tuple. Lors de l’appel de la méthode, la fonction pourra recevoir ce tuple et accéder à ses éléments individuels
Code C# : | Sélectionner tout |
1 2 | var names = LookupName(id); WriteLine($"found {names.Item1} {names.Item3}."); |
Item1 et etc. sont des noms par défaut des éléments d’un tuple et peuvent toujours être utilisés. Ils ne sont pas très descriptifs, il vous est possible de les modifier selon votre convenance. Par exemple
Code C# : | Sélectionner tout |
(string first, string middle, string last) LookupName(long id) // les éléments du tuple ont des noms
Cette fois-ci, lors de l’appel de la méthode, il ne sera plus question de faire appel à Item1 mais plutôt :
Code C# : | Sélectionner tout |
1 2 | var names = LookupName(id); WriteLine($"found {names.first} {names.last}."); |
Il est également possible de spécifier les noms directement dans les littéraux
Code C# : | Sélectionner tout |
return (first: first, middle: middle, last: last); // éléments nommés du tuple dans un littéral
Pour gérer les tuples, une syntaxe de déclaration de déclaration de déconstruction permet aux développeurs de séparer le tuple (ou d’autres ensembles de valeurs) en plusieurs parts et assigner ces parts à de nouvelles variables.
Code C# : | Sélectionner tout |
1 2 | (string first, string middle, string last) = LookupName(id1); // déclaration de déconstruction WriteLine($"found {first} {last}."); |
Dans une déclaration de déconstruction, il est possible d’utiliser var pour les variables individuelles déclarées :
Code C# : | Sélectionner tout |
(var first, var middle, var last) = LookupName(id1); // var à l'intérieur
Ou alors de choisir de mettre un seul var à l’extérieur des parenthèses
Code C# : | Sélectionner tout |
var (first, middle, last) = LookupName(id1); // var à l'extérieur
Il est également possible de déconstruire un tuple dans des variables existantes en se servant d’une affectation de déconstruction :
Code C# : | Sélectionner tout |
(first, middle, last) = LookupName(id2); // affectation de déconstruction
Les améliorations au niveau du littéral permettent de se servir de « _ » comme séparateur de chiffres dans un littéral. Microsoft estime que cela permet d’améliorer la lisibilité et reste sans effet sur la valeur.
Code C# : | Sélectionner tout |
1 2 | var d = 123_456; var x = 0xAB_CD_EF; |
En outre, C # 7.0 introduit la notion de littéraux binaires afin qu’il vous soit possible de spécifier les modèles de bit directement au lieu d’avoir à connaître la notation hexadécimale par cœur.
Code C# : | Sélectionner tout |
var b = 0b1010_1011_1100_1101_1110_1111;
Le nombre de types qui peuvent être retournés par des fonctions asynchrones a été étendu. Microsoft parle aussi des fonctions locales qui permettent aux développeurs de déclarer des fonctions auxiliaires dans le corps d’autres fonctions
Code C# : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | public int Fibonacci(int x) { if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x)); return Fib(x).current; (int current, int previous) Fib(int i) { if (i == 0) return (1, 0); var (p, pp) = Fib(i - 1); return (p + pp, p); } } |
Source : blog Microsoft
Voir aussi :
Visual Studio "15" Preview 4 est disponible, avec un nouveau moteur d'installation qui fait passer la taille de l'installation minimum à 400 Mo