Pourquoi .NET 6 ?

En novembre 2020, Microsoft annonçait la fusion du .NET Framework et du .NET Core 3.x pour créer .NET 5, une plateforme unifiée pour les développeurs combinant dev .NET, cloud, gaming, IoT, web, et IA. Le premier objectif de cette fusion était de permettre aux développeurs (Microsoft et la communauté) de travailler et de développer ensemble en construisant des produits à partir d’une seule et unique base de code. Le second était de produire un environnement d’exécution et une infrastructure .NET uniques qui peuvent être utilisés partout en permettant des comportements d’exécution et des expériences uniformes pour les développeurs.

Après ce premier pas dans l’univers de la plateforme unifiée, Microsoft annonçait la création de .NET 6 en novembre 2021.

Avec .NET 6, Microsoft prévoit de consolider son plan de création d’un univers unifié en capitulant sur les trois principes suivants : 

  • Amélioration de la productivité: .NET 6 couplé à Visual Studio 2022 offrent un rechargement à chaud. Ils mettent à disposition de nouveaux outils Git, une meilleure collaboration entre les équipes, une édition intelligente du code et de nouveaux outils de diagnostic et de tests robustes.
  • Simplification du développement : avec le C# 10, la quantité de code à écrire est considérablement réduite par rapport aux versions antérieures, ce qui facilite sa prise en main. En mettant en place des fonctionnalités telles que le minimal API que nous verrons plus loin dans ce article, il devient plus simple et plus rapide de mettre en place des microservices.
  • Amélioration de la performance : .NET 6 est le framework web full stack le plus rapide du marché. Un avantage non négligeable pour la réduction des coûts de calcul, surtout pour les applications tournant dans le cloud.

Comment donc ces trois principes ont été mis en place ? Nous répondons à cette question dans la suite de l’article.

Les nouveautés

C# 10

.NET 6 embarque avec lui une nouvelle version du langage C#, la version 10. Avec cette nouvelle version du langage, .NET 6 apporte de nombreuses nouvelles fonctionnalités qui aident à écrire du code plus facilement. 

Global Using

On a tous déjà ressenti le besoin d’avoir un fichier répertoriant les espaces de noms auxquels on fait appel dans toutes nos classes. Et qui ne s’est jamais plaint de la redondance des importations d’espaces de noms répétitifs dans ses classes ? Ce ne sera plus le cas avec C#10. 

Le global using nous permet de spécifier une directive using une fois et de l’appliquer à tous les fichiers compilés de l’application. 

  • global using System;
  • global using System.IO;
  • global using System.Text;

Ces déclarations peuvent être placées dans n’importe quel fichier .cs.

Les espaces de noms à l’échelle fichier

Les espaces de noms à l’échelle fichier permettent de déclarer un espace de noms d’un fichier intégralement sans imbriquer le reste du contenu dans des accolades { ….  }. Vu que l’espace a une portée globale sur le fichier entier, il est à noter qu’un seul espace de noms est autorisé et que sa déclaration doit être placée avant toute déclaration de Type. 

namespace MonEspaceDeNom;

class MaClasse { ….. } 

Les cérémonies en C#

Notre premier programme C# contenait une classe embarquée dans un espace de noms, une méthode principale et ses arguments, le tableau de chaîne de caractères string[] args. Avec le C# 10, toutes ces cérémonies deviennent facultatives.

Il devient possible d’écrire directement du code dans un fichier sans se soucier des différentes cérémonies visibles sur l’image en dessous. Un avantage qui peut permettre aux nouveaux apprenants d’améliorer leur courbe d’apprentissage.

Avant .Net 6

Avec .Net 6

Constantes de chaînes de caractères interpolées

L’interpolation de chaînes de caractères est un mécanisme de formatage de ces chaînes. Une chaîne interpolée peut contenir des expressions d’interpolation. Lorsqu’une chaîne interpolée est résolue en une chaîne de résultats, les éléments contenant des expressions d’interpolation sont remplacés par les représentations de chaîne des résultats de l’expression.

Avant le C# 10, il était possible de concaténer des chaînes de caractères. La fonctionnalité d’interpolation de ces chaînes de caractères existait, mais ne permettait pas d’avoir des constantes interpolées.

Avec le C#10, nous pouvons avoir des constantes de chaînes de caractères interpolées desquelles naît une syntaxe plus lisible et plus pratique que le formatage composite des chaînes.

Record struct

Le type record est introduit en C#9. Microsoft lui a apporté une évolution en créant le type record struct avec l’arrivée du C#10.

Le type record a pour but de fournir une syntaxe simple pour déclarer des objets de type référence contenant des propriétés. À la différence des classes, l’égalité dans les records ne signifie pas nécessairement l’égalité des références. Deux instances de record sont égales si les valeurs de toutes leurs propriétés sont égales. Ils peuvent être hérités à l’inverse des structures. Ils exposent également une méthode ToString() retournant chaque propriété ainsi que sa valeur, différente du ToString d’une classe qui retourne le nom du type.

Malgré le fait que le type record soit de type référence, on peut remarquer que l’égalité entre les deux variables est vraie. Ceci s’explique par l’égalité par valeur des différentes propriétés des deux variables. Ce qui n’aurait pas été le cas s’il s’agissait du type classe.

Le type record a connu une évolution avec la création record struct. Il permet de créer des records en tant que structure, donc de type valeur. Un record struct a toutes les fonctionnalités d’un record, mais sera alloué dans la pile comme toute structure et non dans le heap.

Le type record struct utilise aussi donc l’égalité basée sur la valeur. Deux variables de type record struct sont égales si les définitions du type sont identiques et si, pour chaque propriété, les valeurs des deux enregistrements sont égales.

Extended property pattern

Avec le C#8, Microsoft a introduit les property pattern. Un motif permettant de faire correspondre les propriétés d’un objet examiné. 

Le C# 10 vient améliorer ce pattern en simplifiant l’accès aux propriétés imbriquées via l’extended property pattern.

Avec le property pattern depuis C#8 : 

if (e is MethodCallExpression { Method: { Name: « MethodName » } })

Avec l’extended property pattern en C# 10, l’on obtient :

if (e is MethodCallExpression { Method.Name: « MethodName » })

La différence se situe au niveau de la correspondance des propriétés enfants. Avec le property pattern, on observe une imbrication supplémentaire qui n’améliore pas forcément la lisibilité du code tandis qu’avec l’extended property pattern, la correspondance est faite directement via Objet.Propriété.

Mixage entre déclaration et affectation dans la déconstruction de Tuples

Un tuple offre une manière simple de récupérer plusieurs valeurs à partir d’un appel de méthode. Une fois le tuple récupéré, il faut gérer individuellement ses éléments. La déconstruction des tuples permet de décomposer tous les éléments d’un tuple en une seule opération. La syntaxe générale de déconstruction d’un tuple est similaire à la syntaxe qui permet d’en définir un. Les variables auxquelles chaque élément doit être affecté entre parenthèses sont placées dans la partie gauche d’une instruction d’affectation.

Lorsque nous utilisons la déconstruction, nous sommes autorisés à assigner ou à déclarer les variables dans lesquelles nous déconstruisons. Cela signifie que ces deux déconstructions compilent :

// Attribuer des variables par déconstruction

int x = 0; int y = 0;

(x, y) = point; 

// Déclarer des variables par déconstruction

 (int x, int y) = point;

Avant le C# 10, la déconstruction exigeait que toutes les variables soient nouvelles, ou qu’elles soient toutes déclarées au préalable.

Il n’est cependant pas possible de les mélanger dans les versions précédentes du langage. La problématique se situant dans les scénarios où l’une des variables a été préalablement déclarée dans notre code, tandis qu’une autre est obtenue par déconstruction. C#10 lève cette contrainte et nous permet de faire les déclarations et les affectations lors de la déconstruction comme l’illustre le bout de code suivant :

int x = 10; 

(x, int y) = point;

ASP .NET 6

Using implicite

Une nouvelle balise voit le jour dans le .csproj de nos projets, celle du using implicite <ImpliitUsings>

Cette fonctionnalité force le compilateur à importer automatiquement un ensemble de using basé sur le type de projet.

En prenant l’exemple d’une application console, les directives suivantes ne sont plus nécessaires à l’importation ‘explicite’ :

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

Elle porte deux valeurs possibles, qui sont le enable et le disable.

<ImpliitUsings>enable<ImpliitUsings> pour l’activation et
<ImpliitUsings>disable<ImpliitUsings> pour la désactivation. 

Le framework facilite ainsi sa prise en main en prévoyant un ensemble de directives d’importation par type de projet. 

Minimal API

Les minimal APIs permettent aux développeurs de créer des APIs à l’aide d’un seul fichier où ils peuvent configurer l’application, mais aussi écrire le code des points d’entrée API. La nouvelle version du framework simplifie énormément l’écriture des API REST avec le moins de dépendances possibles. 

Dans l’exemple suivant, nous configurons l’application et créons une API d’ajout d’employés directement dans le fichier program.cs.

Elle porte deux valeurs possibles, qui sont le enable et le disable.

<ImpliitUsings>enable<ImpliitUsings> pour l’activation et
<ImpliitUsings>disable<ImpliitUsings> pour la désactivation. 

Le framework facilite ainsi sa prise en main en prévoyant un ensemble de directives d’importation par type de projet. 

Minimal API

Les minimal APIs permettent aux développeurs de créer des APIs à l’aide d’un seul fichier où ils peuvent configurer l’application, mais aussi écrire le code des points d’entrée API. La nouvelle version du framework simplifie énormément l’écriture des API REST avec le moins de dépendances possibles. 

Dans l’exemple suivant, nous configurons l’application et créons une API d’ajout d’employés directement dans le fichier program.cs.

On peut vite remarquer que cette fonctionnalité mise sur la simplicité des approches et le minimalisme. En revanche, elle peut être critiquable sur certains points.

Traditionnellement, la classe startup.cs permet de configurer l’application via deux méthodes et la classe Program.cs, d’ajouter la configuration du serveur web. En fusionnant ces deux fichiers de configuration et en y rajoutant les APIs dans un seul et même fichier, on s’expose au risque d’obtenir à la longue un fichier très volumineux pour des projets appelés à évoluer. 

Et il est important de noter que la documentation d’API est supportée pour les API minimalistes via OpenAPI.

Http logging

La version 6 du .NET Framework permet la configuration et l’activation de la journalisation HTTP en utilisant les méthodes d’extension AddHttpLogging et UseHttpLogging. Leur utilisation active un middleware intégré qui capture les informations sur les requêtes et réponses HTTP, les en-têtes et les informations sur le corps des requêtes, etc.

Pour la configurer, il faut invoquer la méthode d’extension AddHttpLogging appartenant à l’interface IServiceCollection. Le code suivant montre comment procéder.

L’activation est réalisée en invoquant la méthode d’extension UseHttpLogging comme suit : 

app.UseHttpLogging() ;

Aussi intéressant que puisse être la journalisation HTTP, elle peut nuire aux performances de l’application si l’on choisit de logger trop d’éléments, notamment les corps des requêtes et réponses. Il est donc judicieux de tenir compte de l’impact sur les performances au moment de choisir les champs à journaliser.

W3Clogger

Tout comme le HttpLogging, le W3CLogger est un middleware qui écrit des fichiers journaux, à la seule différence que le W3CLogger est au format standard du W3C. Les journaux contiennent des informations sur les requêtes HTTP et les réponses HTTP. W3CLogger fournit des journaux d’information sur les requêtes et réponses HTTP, les en-têtes, les métadonnées sur la paire demande/réponse (date/heure de début, durée), etc.

Pour l’activer, on utilise la méthode UseW3CLogging. Et pour configurer les éléments à logger, on exploite AddW3CLogging.

Enrichissement du .NET BCL

La BCL représente l’une des bibliothèques standard du framework .NET.  Elle fournit des types représentant les types de données CLI intégrés, l’accès de base aux fichiers, les collections, les attributs personnalisés, le formatage, les attributs de sécurité, les flux d’E/S et permet la manipulation des chaînes de caractères, etc. Elle contient également des types de bases fondamentaux, comme System.String et System.DateTime. De nouveaux types et concepts ont été ajoutés au BCL dans cette mise à jour du framework. Les types DateOnly et TimeOnly.

Le type DateTime nous a tous contraints à gérer la partie Time dans bien des situations malgré un besoin limité à la date. Pour pallier ce problème, le type DateOnly se focalise seulement sur les trois propriétés d’une date que sont le jour, le mois et l’année. Ce nouveau type dispose de trois constructeurs illustrés par l’exemple suivant : 

Le premier initialise une date au 01-01-0001, le second au 30 janvier 2022 avec l’ordre des paramètres l’année, le mois et le jour. Le troisième constructeur ajoute la notion de calendrier, dans notre exemple le calendrier grégorien.

Le type TimeOnly, lui, traite la composante temps, notamment de l’heure jusqu’à la milliseconde, selon le besoin. Pour ce faire, il expose 4 différents constructeurs, illustrés ici : 

Le passage de ces structures vers DateTime et TimeSpan est également pris en compte à travers des méthodes telles que ToDateTime pour le DateOnly et le ToTimeSpan pour le TimeOnly

 

Il est important de noter que la sérialisation de ces types n’est pas encore prise en compte dans cette version du framework. Microsoft prévoit de l’intégrer dans la version 7. Une sérialisation de ces deux types propagerait une exception de type NotImplementedException.

Linq

De nombreuses méthodes LINQ ont été ajoutées dans le .NET 6. Ces méthodes sont DistinctBy (), UnionBy (), IntersectBy (), ExceptBy (), MaxBy (), MinBy () and Chunk () que nous détaillerons :

  • DistinctBy () retourne les éléments distincts d’une séquence selon une fonction de sélection de clé.
  • ExceptBy () retourne la différence d’ensemble de deux séquences selon une fonction de sélection de clé.
  • IntersectBy () retourne l’intersection de deux séquences selon une fonction de sélection de clé.
  • UnionBy () produit l’union de deux séquences selon une fonction de sélection de clé. 
  • MinBy () et MaxBy () retournent la valeur minimale pour le MinBy ou maximale pour le MaxBy dans une séquence générique selon une fonction de sélection et éventuellement d’un comparateur de clés spécifiées.
  • Chunk () divise les éléments d’une séquence en morceaux de la taille la plus égale possible à la valeur en paramètre.
  • Et d’autres méthodes ayant leur équivalent dans System.Linq.Queryable.

Les Outils

Cette section n’est pas spécifique à la version du langage utilisée, mais nécessite selon nous un petit focus. Simultanément à la version 6 du framework .NET, Microsoft a sorti une nouvelle édition de son éditeur phare; Visual Studio 2022. 

Visual Studio 2022 est une version purement 64 bits de Visual Studio, un choix qui d’après les responsables du produit permettrait de tirer profit au mieux de toutes les ressources système. Il embarque un certain nombre d’améliorations en matière d’édition et de débogage. Un exemple : il offre la fonction Hot Reload, qui permet aux développeurs de modifier leur code source pendant que leurs applications s’exécutent dans l’éditeur. Il dispose également de capacités de Live Preview et de tests multiplateformes sur Linux, parmi d’autres fonctionnalités nouvelles et améliorées. 

Impacts sur les technologies non prises en charge

Avec cette nouvelle version du framework, des impacts significatifs sont à signaler lors d’une mise à niveau de certains types d’applications.

Pour les applications utilisant les formulaires Web ou Windows Workflow Foundation, l’application devra être réécrite en .NET 6.

ASP.NET Web forms

Depuis .NET 5, la nouvelle orientation de Microsoft est axée sur les bases du .NET Core, et non sur celles du .NET Framework, dont les formulaires Web font partie. Il est donc impossible d’exécuter nos applications ASP.NET Web Forms en utilisant le runtime .NET Core. Mais cela ne signifie pas que Microsoft s’est « débarrassé des formulaires web ». 

Si ASP.NET Web Forms n’est aujourd’hui plus une option prioritaire pour les nouveaux développements, il n’est pas mort pour autant. Nos applications en Web Forms continueront de fonctionner tant que nous aurons du personnel pour les supporter, mais tout comme les applications ASP classiques, elles deviendront de plus en plus fragiles à mesure qu’elles vieillissent.

En bref, nous pouvons continuer à exécuter des applications Web Forms, mais faire le choix de nouvelles technologies pour de nouveaux développements. Pour ce faire, il est recommandé de commencer à tester Razor Pages, Blazor et ASP.NET Core MVC et voir quelle technologie comblera le mieux les lacunes.

Windows workflow foundation

Windows Workflow Foundation nécessite un examen beaucoup plus long. Non seulement il n’est pas porté, mais les composants comme WCF utilisés en complément n’ont pas non plus été portés. CoreWF (le remplacement recommandé de .NET 5) peut devenir assez bon pour de nombreux utilisateurs, mais il n’est pas encore prêt pour la production.

WCF

Les applications WCF doivent également être réécrites. Des outils facilitent cette réécriture, à l’image de l’un d’entre eux qui est une extension de Visual Studio : Visual ReCode. Il aide à la réécriture des applications utilisant le WCF vers le gRPC pour .NET Core et .NET 5+ et il est déjà disponible. Le gRPC est un cadre RPC (Remote Procedure Call) moderne, open source et performant, qui fonctionne dans n’importe quel environnement.

.NET 6 et Azure

Avec sa nouvelle version du framework, les principaux outils PaaS (platform-as-a-service) du cloud Azure ont très rapidement adopté .NET 6. Les principaux services concernés sont Azure Functions, Azure App Service et Azure Static Web Apps.

La prise en main de ces services ne devrait pas être trop difficile, tant la compatibilité est ascendante entre les versions. Pour adopter la nouvelle version du framework, il y a lieu de faire une mise à niveau des environnements de développement et de test locaux avant de réaliser celle de l’application Azure.

 

.NET 6 révolutionne le développement d’applications. Un point clé à noter est son support à long terme étalé sur 3 ans. Un schéma qui se poursuivra pour chaque version paire de .NET (6, 8, 10, etc). Pour de nombreuses organisations, .NET 6 est la première version fiable du nouveau .NET. Elles sont prêtes à l’utiliser, car elles s’en tiennent strictement aux versions LTS (Support à Long Terme). La sortie de .NET 6 est donc un changement de paradigme d’importance.

____________

Si vous souhaitez plus d’informations ou des conseils contactez nos experts Tech.

contactez nos experts

Partager
Faire suivre