Vous n'avez pas encore de notification

Page d'accueil

Options d'affichage

Abonné

Actualités

Abonné

Des thèmes sont disponibles :

Thème de baseThème de baseThème sombreThème sombreThème yinyang clairThème yinyang clairThème yinyang sombreThème yinyang sombreThème orange mécanique clairThème orange mécanique clairThème orange mécanique sombreThème orange mécanique sombreThème rose clairThème rose clairThème rose sombreThème rose sombre

Vous n'êtes pas encore INpactien ?

Inscrivez-vous !

C# 9.0 : de nombreuses nouveautés, souvent inspirées de la programmation fonctionnelle

De F# à C#
C# 9.0 : de nombreuses nouveautés, souvent inspirées de la programmation fonctionnelle

Avant de plonger dans les nouveautés annoncées récemment par Microsoft pour Azure, voici un détour par C#, dont la version 9.0 a été lancée durant la conférence Build. Les nouveautés sont nombreuses, aussi bien pour la pratique usuelle que dans des cas beaucoup plus spécifiques.

Le C# reste aujourd'hui le langage fétiche de Microsoft. Il s'agit pour rappel d'un dérivé du C++, mais de plus haut niveau, puisqu'il reprenait initialement nombre de concepts de Java.

L'éditeur en assure toujours autant la promotion, puisqu'il peut servir aussi bien au développement d'applications natives et .NET que de pages web via ASP.NET. Aussi l'arrivée d'une nouvelle version majeure est-elle toujours un évènement, surtout dans le contexte d'une conférence dédiée aux développeurs.

Comme les connaisseurs pourront s'en apercevoir, beaucoup des apports de C# 9, qui arrive un peu plus d'un an après la version 8, ont trait à la programmation fonctionnelle et sont en fait directement inspirés de F#. Au point que l'on peut se demander aujourd'hui si ce dernier ne sert tout simplement pas de laboratoire d'essai à C#.

Notre dossier sur la Build 2020 de Microsoft :

Place aux propriétés Init-only

On commence avec les propriétés Init-only, qui viennent remédier à certaines limitations des initialiseurs d’objets. Ces derniers offrent en théorie un format flexible, étant particulièrement adaptés à la création imbriquée, pour une arborescence générée d'une traite par exemple. Mais ses propriétés se doivent d'être modifiables.

Les propriétés Init-only corrigent cette situation, les développeurs pouvant désormais se servir d’accesseurs init, variantes des accesseurs set :

public class Personne
{
public string Prénom { get; init; }
public string Nom { get; init; }
}

Dans l’exemple donné par Microsoft, toute affectation ultérieure aux propriétés Prénom et Nom renverra une erreur. Ces accesseurs init ne pouvant être appelés que durant l’initialisation, ils peuvent muter les champs readonly de la classe englobante, comme un développeur le pourrait avec un constructeur.

Cette particularité est utile pour rendre des propriétés individuelles immuables. Dans le cas cependant où il faudrait rendre immuable tout l’objet, on peut utiliser les Records. Dans l’exemple précédent, passer de « public class Person » à « public data class Personne » marque la classe comme Record, lui conférant des comportements de type value.

Ces Records sont davantage définis par leur contenu que par leur identité. Et puisque leur contenu est prévu pour être immuable, les changements dans le temps doivent être représentés par de nouveaux Records. Ils représentent en fait l’état d’un objet à un instant donné.

Les expressions with

Une manière de développer différente, conçue pour des besoins spécifiques, et accompagnée d’un nouveau type d’expressions nommé with. Elles utilisent la syntaxe des initialiseurs d’objets pour marquer la différence d'un nouvel objet pa rapport à un existant. Par exemple, si l’on souhaite créer une nouvelle entrée autrePersonne en récupérant les propriétés de Personne mais en en changeant simplement Nom, on obtient :

var autrePersonne = personne with { Nom = "Dupont" };

En arrière-plan, un constructeur de copie labellisé protected s’occupe de gérer l’opération.

Nouveaux patterns et opérateurs

Plusieurs types de nouveaux patterns font leur apparition dans C# 9.0.

public static decimal CalculateToll(object vehicle) =>
vehicle switch
{
...
DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m,
DeliveryTruck _ => 10.00m,
_ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle))
};

L’exemple fourni montre la manière dont le code devait être écrit jusqu’à présent pour le pattern matching. Dans C# 9.0, plusieurs éléments peuvent être notablement simplifiés. Par exemple, plus besoin de déclarer un identifiant de pattern, même un _. Le développeur peut ainsi écrire directement le type : DeliveryTruck => 10.00m,

Du changement également pour les opérateurs relationnels de type < ou <=. La partie DeliveryTruck peut alors s’écrire comme une expression switch imbriquée, > 5000 et < 3000 étant des patterns relationnels :

DeliveryTruck t when t.GrossWeightClass switch
{
> 5000 => 10.00m + 5.00m,
< 3000 => 10.00m - 2.00m,
_ => 10.00m,
},

Des opérateurs logiques and, or et not apparaissent dans la foulée. On peut par exemple écrire >= 3000 and <= 5000 => 10.00m, pour représenter un intervalle. L’opérateur not parle de lui-même et peut s’appliquer à de multiples situations. Par exemple pour définir des cas, en accompagnement de null.

Autre cas classique, dans l’utilisation d’expressions if, pour spécifier une action si une variable n’a pas la valeur spécifiquement définie, sans requérir de double parenthèses : if (e is not Customer) { ... }

Target typing, retours covariants et autres améliorations

C# 9.0 améliore le target typing, qui survient lorsqu’une expression obtient un type depuis le contexte de son utilisation. La nouvelle version allonge la liste des expressions prises en charge. Dans new par exemple, plus besoin de spécifier le type dans la plupart des cas, comme dans Point p = new (3, 5);

On note d’autres nouveautés, comme les retours covariants, s’adressant à des cas particuliers, pour signaler qu’un forçage (override) de méthode dans une classe dérivée a un type de retour plus spécifique que la déclaration dans le type de base. Signalons aussi les fonctions lambdas statiques. La déclaration peut ainsi être accompagnée d’un mot servant de préfixe, la fonction lambda se comportant alors comme une méthode statique. Cela évite notamment la capture de paramètres.

Dans la liste des simplifications, on note celle du code de base d'une application passant de :

using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Hello World!");
    }
}

À une solution plus légère, où il est possible de se contenter de débuter le code directement après les using, mais avant toute déclaration d'un espace de nom, précise Microsoft :

using System;
Console.WriteLine("Hello World!");

N'importe quelle fonctionnalité est disponible, des retours de code de statut à await en passant par les arguments (args), tant que tout est contenu dans un seul et même fichier. De quoi éviter des déclarations comme celles d'une méthode principale et d'une classe, inutiles pour une application très basique. 

On pourrait également citer une simplification de la validation null standard par l’ajout d’une petite annotation, les initialiseurs de modules, la reconnaissance de la méthode GetEnumerator dans les boucles foreach ou encore l’extension des méthodes Partial, en supprimant notamment toutes les restrictions autour de leur signature.

Les développeurs intéressés pourront se rendre par ici où les changements sont détaillés. Mais aussi lire la liste complète des nouveautés depuis la page de statut du langage sur le dépôt GitHub associé. Une vidéo a également été mise en ligne à l'occasion de l'édition numérique de la Build 2020 :

34 commentaires
Avatar de fdorin Abonné
Avatar de fdorinfdorin- 03/06/20 à 06:44:09

A noter que pour profiter pleinement des dernières nouveautés du langage (C# 8 et ultérieur !), il ne faut pas utiliser .NET Framework, mais .NET Core (ou plus précisément, un framework compatible .NET Standard 2.1 et ultérieur).

.NET Framework ne sera pas pleinement compatible, car certaines fonctionnalités nécessite des modifications au niveau du CLR (Common Language Runtime), qui, dans ce cas précis, ne sera pas mis à jour pour des raisons de pérennité.

Avatar de ndjpoye Abonné
Avatar de ndjpoyendjpoye- 03/06/20 à 07:05:38

Pourquoi avoir mis ça dans le même dossier que les articles concernant la Build 2020 de windows ?

Bon sinon moi, je n'aime pas cette évolution vers le fonctionnel. Je dois être passé du côté des vieux bougons  :transpi:

Édité par ndjpoye le 03/06/2020 à 07:06
Avatar de Nicky5 Abonné
Avatar de Nicky5Nicky5- 03/06/20 à 07:26:46

Il y a quelques truc très intéressants comme le not et la version Crosoft du Final, mais le reste aussi simplifiant soit il ne fait que rendre le code encore plus illisible :craint:

Je continuerais comme dab avec mes étudiants en leurs montrant comment être verbeux, car il est toujours plus facile de passer de verbeux à crado que l'inverse...

Avatar de jpaul Abonné
Avatar de jpauljpaul- 03/06/20 à 07:41:26

C'est pas dégueu comme évolutions. C# et .NET ne m'a jamais vraiment attiré mais j'avoue que depuis .NET Core et C# 8 et 9 maintenant, on sent que Microsoft n'a pas du tout l'intention de laisser stagner son (pourtant vieux) bébé.

Je trouve assez chelou d'utiliser le mot clé switch pour le pattern matching avec une syntaxe totalement différence du switch classique là où la plupart des langages proposent soit switch et match, soit uniquement match. Mais bon c'est du pinaillage.

Avatar de jpaul Abonné
Avatar de jpauljpaul- 03/06/20 à 07:48:34

ndjpoye a écrit :

Pourquoi avoir mis ça dans le même dossier que les articles concernant la Build 2020 de windows ?

Bon sinon moi, je n'aime pas cette évolution vers le fonctionnel. Je dois être passé du côté des vieux bougons  :transpi:

Nicky5 a écrit :

Il y a quelques truc très intéressants comme le not et la version Crosoft du Final, mais le reste aussi simplifiant soit il ne fait que rendre le code encore plus illisible :craint:

Je continuerais comme dab avec mes étudiants en leurs montrant comment être verbeux, car il est toujours plus facile de passer de verbeux à crado que l'inverse...

Franchement pour essayer de faire un peu de fonctionnel en ce moment, on en est encore loin sur C#.

Néanmoins je trouve l'approche intéressante et franchement c'est pas du tout incompatible avec la "verbosité". La seule "difficulté" qu'il faut que vous mettiez de côté, c'est appréhender la nouvelle syntaxe, mais une fois ceci fait, vous vous rendre compte que, au contraire, tout ce qui est supprimé, ce sont justement les éléments souvent à risque d'être "mal nommés" que sont les paramètres et variables utilisés deux fois dans une même ligne, qu'on a tendance à nommer d'un seul caractère.

Avatar de ndjpoye Abonné
Avatar de ndjpoyendjpoye- 03/06/20 à 07:52:16

jpaul a écrit :

C'est pas dégueu comme évolutions. C# et .NET ne m'a jamais vraiment attiré mais j'avoue que depuis .NET Core et C# 8 et 9 maintenant, on sent que Microsoft n'a pas du tout l'intention de laisser stagner son (pourtant vieux) bébé. 

Pour un langage, il n'est pas si vieux que ça, il a moins de 20 ans. Il fait presque partie des jeunes adultes :)

Avatar de ndjpoye Abonné
Avatar de ndjpoyendjpoye- 03/06/20 à 07:58:10

jpaul a écrit :

Franchement pour essayer de faire un peu de fonctionnel en ce moment, on en est encore loin sur C#.

Néanmoins je trouve l'approche intéressante et franchement c'est pas du tout incompatible avec la "verbosité". La seule "difficulté" qu'il faut que vous mettiez de côté, c'est appréhender la nouvelle syntaxe, mais une fois ceci fait, vous vous rendre compte que, au contraire, tout ce qui est supprimé, ce sont justement les éléments souvent à risque d'être "mal nommés" que sont les paramètres et variables utilisés deux fois dans une même ligne, qu'on a tendance à nommer d'un seul caractère.

Ha mais, j'assume mon côté vieux bougons :transpi: 
De mon point de vue, on peut faire du crado illisible avec ou sans ces changements. Mais c'est juste que j'aurais du mal à m'habituer à certaines nouvelles syntaxes. J'ai déjà du mal avec l'usage à tout bout de champ du mot clef var. Une part est due  à la force de l'habitude :)
Mais je n'ai rien contre le fonctionnel. 

Avatar de fdorin Abonné
Avatar de fdorinfdorin- 03/06/20 à 08:00:11

ndjpoye a écrit :

Pourquoi avoir mis ça dans le même dossier que les articles concernant la Build 2020 de windows ?

Peut être car il ne s'agit pas d'une référence à la dernière build de Windows, mais de MS Build 2020, une série de conférences organisée par Microsoft, durant laquelle est faite de nombreuses annonces (dont C# 9) ;)

Avatar de ndjpoye Abonné
Avatar de ndjpoyendjpoye- 03/06/20 à 08:03:46

fdorin a écrit :

Peut être car il ne s'agit pas d'une référence à la dernière build de Windows, mais de MS Build 2020, une série de conférences organisée par Microsoft, durant laquelle est faite de nombreuses annonces (dont C# 9) ;)

Rhooo punaise, mais oui biensur. Je suis un boulet, merci :)

Ca m'apprendra à poster sans avoir ma dose minimale de caféine dans le sang :transpi:

Avatar de jpaul Abonné
Avatar de jpauljpaul- 03/06/20 à 08:16:54

Ben, moi ce que j'aime avec ces langages multi-paradigmes, c'est que tu peux justement à la fois être verbeux sur la partie structurante (ex la partie web) mais aussi profiter de la syntaxe fonctionnelle pour exprimer ton métier de manière plus concise (et donc plus lisible).

J'ai de petits projets sans prétention en C# + F# pour apprendre un peu le fonctionnel, et c'est assez cool de pouvoir écrire la partie web et technique en impératif tout en exprimant totalement ton métier en F#, qui a pour lui une syntaxe de création de type extrêmement courte, qui t'encourage à créer un nouveau type pour quasiment chaque utilisation.

Si tu veux un exemple sympa, tu as ici un seul fichier F# qui définit toutes les règles métier d'un jeu d'échec :https://github.com/JordanMarr/FsharpChess/blob/master/Chess.Domain/Chess.fs et, si je peux confirmer que quand tu débutes c'est assez difficile à écrire (syntaxe + modèle mental à changer totalement) je trouve assez fascinant à quel point, même en ayant jamais fait de programmation fonctionnelle, ni jamais lu la moindre ligne de F#, c'est extrêmement expressif et facile à lire. Tu peux quasiment faire lire ce bout de code a responsable produit ou au client pour qu'il valide que c'est bien ce qu'il veut.

Et le truc le plus merveilleux, c'est que tu peux ajouter le .fsproj contenant ce code dans un .sln et appeler ces fonctions comme si elles étaient de bêtes méthodes statiques.

Il n'est plus possible de commenter cette actualité.
Page 1 / 4