URL: https://linuxfr.org/news/net-6-est-sorti-la-version-la-plus-rapide-a-ce-jour
Title: .NET 6 est sorti - La version la plus rapide à ce jour
Authors: xcomcmdr
Nils Ratusznik, Benoît Sibaud, Pierre Maziere, Ysabeau, Xavier Claude, palm123, Yves Bourguignon, Bruno Ethvignot, Ltrlg et Florent Zara
Date: 2021-10-02T11:25:49+02:00
License: CC By-SA
Tags: dotnet
Score: 3
La dernière version du cadriciel libre (sous licence [MIT](https://fr.wikipedia.org/wiki/Licence_MIT)) et multiplateforme est apparue le 9 novembre 2021. C’est une version majeure, avec **énormément** de nouveautés et comme toujours des performances améliorées. Voyons ensemble pourquoi ce cadriciel est [si](https://insights.stackoverflow.com/survey/2020#technology-most-loved-dreaded-and-wanted-web-frameworks-loved2) [apprécié](https://insights.stackoverflow.com/survey/2020#technology-most-loved-dreaded-and-wanted-other-frameworks-libraries-and-tools-loved3).
La version 6 de .Net représente un an d’efforts. Elle apporte son lot d’améliorations du langage, des [performances](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/) ainsi que la première prise en charge de manière native des processeurs [Apple Silicon](https://fr.wikipedia.org/wiki/Apple_Silicon) ([Arm64](https://fr.wikipedia.org/wiki/Architecture_ARM)). Elle dispose aussi :
- d’un nouveau système d’optimisation dynamique guidée par le profil (_Profil Guided Optimization_)
- de diagnostics améliorés via [OpenTelemetry](https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/)
- des [améliorations pour dotnet monitor](https://devblogs.microsoft.com/dotnet/whats-new-in-dotnet-monitor/)
- de la prise en charge de bibliothèques natives au sein d’une application [WebAssembly](https://fr.wikipedia.org/wiki/WebAssembly)
- de nouvelles API pour [HTTP/3](https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/), [le traitement du JSON](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/), les [mathématiques](https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/) et la [manipulation directe de la mémoire](https://docs.microsoft.com/fr-fr/dotnet/api/system.runtime.interopservices.nativememory?view=net-6.0)
- et bien d’autres choses, voir ci-dessous pour bien plus de détails.
----
[Announcing .NET 6 — The Fastest .NET Yet](https://devblogs.microsoft.com/dotnet/announcing-net-6/)
[Announcing ASP.NET Core in .NET 6](https://devblogs.microsoft.com/dotnet/announcing-asp-net-core-in-net-6/)
[Welcome to C# 10](https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/)
[F# 6 is officially here!](https://devblogs.microsoft.com/dotnet/fsharp-6-is-officially-here/)
[.NET Conf 2021](https://www.dotnetconf.net/)
[.NET 6 (téléchargement)](https://dotnet.microsoft.com/download/dotnet/6.0)
[Notes de version](https://github.com/dotnet/core/blob/main/release-notes/6.0/README.md)
----
Introduction
============
.NET 6 est le résultat d’un peu plus d’un an d’efforts de la part de l’équipe .NET et de la communauté. C# 10 et F# 6 apportent des améliorations au langage qui rendent votre code plus simple et meilleur. Comme pour chaque [nouvelle](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/) [version](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/), il y a [des améliorations énormes de performance](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/).
Par ailleurs, .NET 6 est la première version qui prend en charge de manière native l'[Apple Silicon](https://fr.wikipedia.org/wiki/Apple_Silicon) ([Arm64](https://fr.wikipedia.org/wiki/Architecture_ARM)) et a également été améliorée pour Windows Arm64. Nous avons construit un nouveau système d’optimisation dynamique, guidée par le profil (**P**rofil **G**uided **O**ptimization) qui offre des optimisations importantes impossibles à mettre en œuvre avec la [compilation à la volée](https://fr.wikipedia.org/wiki/Compilation_%C3%A0_la_vol%C3%A9e) traditionnelle (JIT).
Les diagnostics dans le cloud ont été améliorés au travers de [OpenTelemetry](https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/) et des dernières [évolutions de dotnet monitor](https://devblogs.microsoft.com/dotnet/whats-new-in-dotnet-monitor/). La prise en charge de [WebAssembly](https://fr.wikipedia.org/wiki/WebAssembly) est plus performante. De nouvelles API ont été ajoutées, pour [HTTP/3](https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/), [le traitement du JSON](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/), les [mathématiques](https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/) et la [manipulation directe de la mémoire](https://docs.microsoft.com/fr-fr/dotnet/api/system.runtime.interopservices.nativememory?view=net-6.0). .NET 6 est une version majeure et ainsi sera [pris en charge pendant trois ans](https://github.com/dotnet/core/blob/main/releases.md). Les développeurs ont déjà commencé à mettre à niveau leurs applications vers .NET 6 (NdT: comme votre serviteur) et les premiers résultats obtenus en production sont excellents.
.NET 6 est prêt pour votre application.
Vous pouvez [télécharger .NET 6](https://dotnet.microsoft.com/download/dotnet/6.0) pour [Linux](https://fr.wikipedia.org/wiki/Linux), [macOS](https://fr.wikipedia.org/wiki/MacOS), et [Windows](https://fr.wikipedia.org/wiki/Microsoft_Windows).
- [installeurs et binaires](https://dotnet.microsoft.com/download/dotnet/6.0)
- [images docker](https://hub.docker.com/_/microsoft-dotnet)
- [paquets Linux](https://github.com/dotnet/core/blob/main/release-notes/6.0/install-linux.md)
- [Notes de version](https://github.com/dotnet/core/blob/main/release-notes/6.0/README.md)
- [Différence d’API](https://github.com/dotnet/core/blob/main/release-notes/6.0/preview/api-diff/rc1/README.md)
- [Problèmes connus](https://github.com/dotnet/core/blob/main/release-notes/6.0/known-issues.md)
- [Suivie des problèmes sur GitHub](https://github.com/dotnet/core/issues/6881)
[Visual Studio 2022](https://devblogs.microsoft.com/visualstudio/visual-studio-2022-now-available/) est aussi désormais disponible. (NdT : pour les gens n’utilisant pas Windows, il y a notamment [Visual Studio Code](https://code.visualstudio.com/) ou [Rider](https://www.jetbrains.com/fr-fr/rider/) de [JetBrains](https://fr.wikipedia.org/wiki/JetBrains)).
[PowerShell 7.2](https://devblogs.microsoft.com/powershell/general-availability-of-powershell-7-2), basé sur .NET 6, est également disponible. Les utilisateurs de PowerShell ont accès aux mêmes améliorations de performance et API que les développeurs .NET.
Pour rappel, [PowerShell Core](https://github.com/PowerShell/PowerShell) est un outil et un cadre d’automatisation et de configuration multiplateforme (Windows, Linux et macOS) qui fonctionne bien avec vos outils existants et qui est optimisé pour traiter les données structurées (par exemple, JSON, CSV, XML, etc.), les API REST et les modèles objets. Il comprend un interpréteur de ligne de commande, un langage de script associé et un cadriciel pour le traitement des [cmdlets](https://fr.wikipedia.org/wiki/Windows_PowerShell#Syntaxe).
Si vous préférez découvrir les dernières fonctionnalités de .NET 6 à l’aide d’une discussion approfondie ou en vidéo, les [conversations](https://devblogs.microsoft.com/dotnet/category/conversations/) d’ingénieur à ingénieur sont disponibles, ainsi que la [.NET Conf](https://dotnetconf.net/).
Les points clés
===============
.NET 6 est :
- **Testé de manière extensive en production** avec les services Microsoft, [les applications dans le cloud gérées par d’autres entreprises](https://twitter.com/nycdotnet/status/1438970921302347778) et [les projets open source](https://github.com/jellyfin/jellyfin/pull/6806) ;
- **Prise en charge pendant trois ans** en tant que [dernière version de support à long terme (LTS)](https://github.com/dotnet/core/blob/main/releases.md) ;
- **Une plateforme unifiée** pour les [navigateurs](https://github.com/dotnet/aspnetcore/tree/main/src/Components), le [cloud](https://github.com/dotnet/aspnetcore), les applications [desktop](https://github.com/dotnet/winforms), [IoT](https://github.com/dotnet/iot/) et [mobiles](https://github.com/dotnet/maui), tous utilisant les mêmes bibliothèques .NET et la possibilité de partager facilement le code ;
- **Des performances** [grandement améliorées dans tous les domaines](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/) [notamment pour les E/S relatives aux fichiers](https://devblogs.microsoft.com/dotnet/file-io-improvements-in-dotnet-6/), ce qui, ensemble, entraîne une diminution du temps d’exécution, de la latence et de l’utilisation de la mémoire ;
- **C# 10** offre des améliorations du langage telles que les [structures d’enregistrement](https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/) (_record structs_), les _usings_ implicites et des améliorations pour l’usage des lambdas, tandis que le compilateur ajoute des générateurs de sources incrémentiels. [F# 6 ajoute de nouvelles fonctionnalités, notamment l’asynchronisme basé sur les tâches, le débogage du pipeline et de nombreuses améliorations des performances](https://linuxfr.org/redirect/109400) ;
- **Le rechargement à chaud** (_Hot Reload_) vous permet d’éviter de recompiler et de redémarrer votre application pour visualiser une nouvelle modification, alors que votre application est en cours d’exécution. Cette fonction est prise en charge dans Visual Studio 2022 et à partir de la ligne de commande dotnet (NdT : au travers de [_dotnet watch_](https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-6.0)), pour C# et VB .NET ;
- **Les diagnostics dans le cloud** ont été améliorés avec [OpenTelemetry](https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/) et [dotnet monitor,](https://devblogs.microsoft.com/dotnet/whats-new-in-dotnet-monitor/) qui est désormais pris en charge en production et disponible avec _Azure App Service_.
- **Les API JSON** [ont été étendues](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/) et offrent de meilleures performances grâce à un générateur de source pour le sérialiseur ;
- **Les _Minimal APIs_** ont été introduites dans ASP.NET Core pour [baisser la barrière à l’entrée](https://www.hanselman.com/blog/exploring-a-minimal-web-api-with-aspnet-core-6) et améliorer les performances des services HTTP ;
- **Les composants Blazor** [peuvent maintenant être affichés à partir de JavaScript](https://docs.microsoft.com/aspnet/core/blazor/components/?view=aspnetcore-6.0#render-razor-components-from-javascript) et intégrés avec des applications existantes basées sur JavaScript ;
- La compilation AOT (_**A**head **O**f **T**ime_) pour [les applications Blazor WebAssembly (Wasm)](https://docs.microsoft.com/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-6.0#ahead-of-time-aot-compilation), apporte la prise en charge de dépendances natives dans le navigateur ;
- **Les applications monopages** (_**S**ingle **P**age **A**pplications_) construites avec ASP.NET Core utilisent désormais un modèle plus flexible qui peut être utilisé avec [Angular](https://fr.wikipedia.org/wiki/Angular), [React](https://fr.wikipedia.org/wiki/React) ainsi que d’autres frameworks JavaScript frontaux populaires ;
- **HTTP/3** a été ajouté afin qu’ASP.NET Core, HttpClient et gRPC puissent tous interagir [avec les clients et serveurs HTTP/3](https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6/) ;
- **L’API pour les E/S basées sur des fichiers** prend désormais en charge les liens symboliques et ses performances ont été considérablement améliorées grâce à une réécriture complète de [FileStream](https://docs.microsoft.com/en-us/dotnet/api/system.io.filestream?view=net-6.0) ;
- **La sécurité** a été améliorée grâce à la prise en charge d'[OpenSSL 3](https://www.openssl.org/blog/blog/2021/09/07/OpenSSL3.Final/), du schéma de chiffrement [ChaCha20Poly1305](https://cryptopp.com/wiki/ChaCha20Poly1305) et des mesures d’atténuation de la défense en profondeur au moment de l’exécution, notamment [`W^X`](https://github.com/dotnet/designs/blob/main/accepted/2021/runtime-security-mitigations.md#wx) et [CET](https://github.com/dotnet/designs/blob/main/accepted/2021/runtime-security-mitigations.md#intel-control-flow-enforcement-technology-cet) ;
- **Les applications à fichier unique** (sans extraction d’archive) peuvent être publiées pour Linux, macOS et Windows (auparavant c’était uniquement pour Linux) ;
- **L'[élagage du langage intermédiaire](https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options)** (_IL Trimming_) est désormais plus performant et efficace, avec de nouveaux avertissements et analyseurs pour garantir des résultats finaux corrects ;
- **Des générateurs et des analyseurs de sources** ont été ajoutés pour vous aider à produire un code meilleur, plus sûr et plus performant ;
- **La compilation de sources** permet à des organisations comme [Red Hat](https://fr.wikipedia.org/wiki/Red_Hat) de compiler .NET à partir des sources et de proposer leurs propres builds à leurs utilisateurs.
Cette nouvelle version inclut environ [dix mille commits git](https://github.com/dotnet/sdk/commits/release/6.0.2xx). Malgré la longueur de cet article, il passe sous silence de nombreuses améliorations. Vous devrez télécharger et essayer .NET 6 pour voir toutes les nouveautés.
Prise en charge
=======
.NET 6 est une version LTS (Long-term Support) qui sera [prise en charge pendant trois ans](https://github.com/dotnet/core/blob/main/releases.md). [Elle est prise en charge sur plusieurs systèmes d’exploitation](https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md), notamment macOS Apple Silicon, Debian, Ubuntu, Alpine Linux, CentOS, OpenSUSE, RHEL, Fedora, et SLES, ainsi que Windows.
[Red Hat prend en charge .NET](http://redhatloves.net/) sur Red Hat Enterprise Linux, en collaboration avec l’équipe .NET. Sur RHEL 8 et plus, .NET 6 sera disponible pour les architectures AMD et Intel (x64_64), ARM (aarch64), ainsi que [IBM Z et LinuxONE (s390x)](https://community.ibm.com/community/user/ibmz-and-linuxone/blogs/elizabeth-k-joseph1/2021/11/10/net-6-comes-to-ibm-z-and-linuxone).
Veuillez commencer à migrer vos applications vers .NET 6, en particulier les applications .NET 5. Les premiers retours utilisateurs nous ont indiqué que la mise à niveau vers .NET 6 était simple à partir de .NET Core 3.1 ou .NET 5.
.NET 6 est pris en charge par [Visual Studio 2022](https://visualstudio.microsoft.com/vs) et [Visual Studio 2022 pour Mac](https://visualstudio.microsoft.com/vs/mac/). .NET 6 est pris en charge aussi avec [l’extension Visual Studio Code pour C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp).
Azure App Service
-------------------
- Azure Functions [prend désormais en charge l’exécution de fonctions sans serveur dans .NET 6](https://go.microsoft.com/fwlink/?linkid=2178604) ;
- [L’annonce de la disponibilité générale](https://go.microsoft.com/fwlink/?linkid=2178304) d’App Service en version .NET 6 contient des informations et des détails pour les développeurs ASP.NET Core impatients d’utiliser .NET 6 dès aujourd’hui ;
- Azure Static Web Apps [prend désormais en charge les applications .NET 6 complètes avec les frontaux Blazor WebAssembly et les API Azure Function](https://go.microsoft.com/fwlink/?linkid=2178605).
Remarque : si votre application exécute déjà une version .NET 6 Preview ou RC sur App Service, elle sera mise à jour automatiquement au premier redémarrage une fois que le moteur d’exécution et le SDK .NET 6 seront déployés dans votre région. Si vous avez déployé une application autonome, vous devrez la recompiler et la redéployer.
Une plateforme unifiée et étendue
=================================
![Plateforme unifiée](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/dotnet-unified-platform.png)
.NET 6 offre une plateforme unifiée, pour les applications de [navigateur](https://github.com/dotnet/aspnetcore/tree/main/src/Components), de [cloud](https://github.com/dotnet/aspnetcore), de [bureau](https://github.com/dotnet/winforms), d'[IoT](https://github.com/dotnet/iot/) et [mobiles](https://github.com/dotnet/maui). La plateforme sous-jacente a été mise à jour pour répondre aux besoins de tous les types d’apps et pour faciliter la réutilisation du code dans toutes vos apps. Les nouvelles capacités et améliorations sont disponibles pour toutes les apps en même temps, de sorte que votre code exécuté dans le cloud ou sur un appareil mobile se comporte de la même manière et bénéficie des mêmes avantages.
La portée des développeurs .NET continue de s’élargir à chaque version. [L’apprentissage automatique (_Machine Learning_)](https://github.com/dotnet/machinelearning) et [WebAssembly](https://docs.microsoft.com/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-6.0#ahead-of-time-aot-compilation) sont deux des ajouts les plus récents. Par exemple, avec l’apprentissage automatique, vous pouvez écrire des applications qui recherchent des anomalies dans les données en continu. Avec WebAssembly, vous pouvez [héberger des applications .NET dans le navigateur](http://blazor.net/), tout comme HTML et JavaScript, [ou les combiner avec HTML et JavaScript](https://docs.microsoft.com/aspnet/core/blazor/components/?view=aspnetcore-6.0#render-razor-components-from-javascript).
L’un des ajouts les plus intéressants est l['interface utilisateur multiplateforme de .NET (.NET MAUI)](https://github.com/dotnet/maui). Vous pouvez désormais écrire du code – dans un seul projet – qui offre une expérience d’application client moderne sur les systèmes d’exploitation mobiles et de bureau (NdT : sauf le bureau Linux, pour ça il y [AvaloniaUI](https://avaloniaui.net/)). .NET MAUI sera publié un peu plus tard que .NET 6. Nous avons consacré beaucoup de temps et d’efforts à .NET MAUI et nous sommes très enthousiastes à l’idée de le mettre à disposition et de voir les applications .NET MAUI en production.
Bien entendu, les applications .NET sont toujours à l’aise sur le bureau [Windows](https://docs.microsoft.com/dotnet/desktop/) – avec [Windows Forms](https://github.com/dotnet/winforms) et [WPF](https://github.com/dotnet/wpf) – et dans le cloud avec [ASP.NET Core](https://fr.wikipedia.org/wiki/ASP.NET_Core).
Ce sont les types d’applications que nous proposons depuis très longtemps et elles continuent d’être très populaires.
Nous les avons améliorées dans .NET 6.
Cibler .NET 6
=============
Toujours dans l’optique d’une plate-forme étendue, il est facile d’écrire du code .NET sur tous ces systèmes d’exploitation.
Pour cibler .NET 6, vous devez utiliser un cadre cible .NET 6, comme le suivant :
```xml
net6.0
```
L’identifiant net6.0 (_Target Framework Moniker_) vous donne accès à toutes les API multiplateformes offertes par .NET. C’est la meilleure option si vous écrivez des applications console, des applications Web ou des bibliothèques multiplateformes réutilisables.
Si vous ciblez un système d’exploitation spécifique (comme si vous écrivez une application Windows Forms ou iOS), il existe un autre ensemble de TFM (qui ciblent chacun un système d’exploitation évident) que vous pouvez utiliser. Ils vous donnent accès à toutes les API de net6.0, plus un certain nombre d’API spécifiques au système d’exploitation.
```cmd
net6.0-android
net6.0-ios
net6.0-maccatalyst
net6.0-tvos
net6.0-windows
```
Les TFM sans version équivalent chacun à cibler la version de système d’exploitation la plus basse prise en charge par .NET 6. Vous pouvez spécifier une version de système d’exploitation si vous voulez être spécifique ou avoir accès à des API plus récentes.
Les modules TFM net6.0 et net6.0-windows sont pris en charge (comme pour .NET 5). Les TFM Android et Apple sont nouveaux avec .NET 6 et sont actuellement en phase d’aperçu. Ils seront pris en charge lors d’une mise à jour ultérieure de .NET 6.
Il n’y a pas de relations de compatibilité entre les TFM spécifiques au système d’exploitation. Par exemple, net6.0-ios n’est pas compatible avec net6.0-tvos. Si vous souhaitez partager du code, vous devez le faire avec des sources avec des déclarations #if ou des binaires avec du code ciblé net6.0 (NdT : vous pouvez aussi utiliser l’attribut [SupportedOSPlatform](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.versioning.supportedosplatformattribute?view=net-6.0) allié à la classe [OperatingSystem](https://docs.microsoft.com/en-us/dotnet/api/system.operatingsystem?view=net-6.0), c’est détaillé plus loin).
Les nouveautés pour le développement Web
========================================
Voici un échantillon [des nouvelles fonctionnalités et améliorations pour ASP.NET Core pour .NET 6](https://devblogs.microsoft.com/dotnet/announcing-asp-net-core-in-net-6/) :
- **Rechargement à chaud** (_Hot Reload_) : Appliquez les modifications apportées aux fichiers sources Razor, C# et CSS dans votre application en cours d’exécution pendant le développement sans avoir à recompiler et à redémarrer l’application ;
- **API minimales** : Créez une nouvelle application ASP.NET Core avec seulement quelques lignes de code en utilisant les dernières fonctionnalités C# et un modèle d’hébergement simplifié ;
- **Streaming asynchrone** : Diffusez des données de manière asynchrone depuis le serveur sans avoir besoin de mettre en mémoire tampon ;
- **IAsyncDisposable** : Prise en charge de [IAsyncDisposable](https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync) sur les contrôleurs, les modèles de page et les composants de vue. Cela permet de libérer une ressource native (socket réseau, mémoire native…) sans bloquer le code appelant ;
- **Bootstrap 5.1** : ASP.NET Core embarque désormais [Bootstrap](https://fr.wikipedia.org/wiki/Bootstrap_(framework)) 5.1 ;
- **Analyse des références nulls** : L’analyse des références nulls en C# est désormais activée par défaut pour tous les patrons de conception (templates) pour les projets Web. Pour rappel, les [Nullable Reference Types](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references) permet d’éviter les NullReferenceException _avant_ d’exécuter le code. [Les annotations](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-migration-strategies) ajoutées au code source de ASP .NET Core permettent désormais au compilateur de détecter davantage de cas et d’émettre un _Warning_ ;
- **[Isolation CSS pour les pages et les vues](https://docs.microsoft.com/aspnet/core/razor-pages/#css-isolation)** : Étendez les styles CSS à des pages ou des vues spécifiques à l’aide de fichiers .cshtml.css. Fini les conflits !
- **[Modules JavaScript](https://docs.microsoft.com/aspnet/core/blazor/javascript-interoperability/#load-a-script-from-an-external-javascript-file-js-collocated-with-a-component)** : Placez des modules JavaScript connexes à côté des pages, des vues et des composants à l’aide des fichiers .cshtml.js et .razor.js.
Améliorations concernant [Blazor](https://fr.wikipedia.org/wiki/Blazor)
-----------------------------------------------------------------------------
- [Rendu des composants Blazor à partir de JavaScript](https://docs.microsoft.com/aspnet/core/blazor/components/#render-razor-components-from-javascript) ;
- [Préservation de l’état du pré-rendu](https://docs.microsoft.com/aspnet/core/blazor/components/prerendering-and-integration#preserve-prerendered-state) ;
- [Limites d’erreur](https://docs.microsoft.com/aspnet/core/blazor/fundamentals/handle-errors#error-boundaries) ;
- [Arguments d’événements personnalisés](https://docs.microsoft.com/aspnet/core/blazor/components/event-handling#custom-event-arguments) ;
- [Déduction des paramètres de type générique à partir des composants précédents](https://docs.microsoft.com/aspnet/core/blazor/components/templated-components#infer-generic-types-based-on-ancestor-components) ;
- [Paramètres de composants requis](https://docs.microsoft.com/aspnet/core/blazor/components/#component-parameters) ;
- [Gestion du _query-string_](https://docs.microsoft.com/aspnet/core/blazor/fundamentals/routing#query-strings) ;
- [Contrôle du contenu de l’en-tête HTML](https://docs.microsoft.com/aspnet/core/blazor/components/control-head-content) ;
- [Initialiseurs JavaScript](https://docs.microsoft.com/aspnet/core/blazor/fundamentals/startup#javascript-initializers) ;
- [Rendu dynamique des composants](https://docs.microsoft.com/aspnet/core/blazor/components/dynamiccomponent).
Pour rappel, Blazor est un framework d’application Web permettant d’éviter entièrement JavaScript. Les applications Blazor reposent sur des composants, plutôt que sur le pattern [Modèle-Vue-Contrôleur](https://fr.wikipedia.org/wiki/Mod%C3%A8le-vue-contr%C3%B4leur) traditionnel. Ce modèle traditionnel est toujours présent et bien vivant pour les utilisateurs de [ASP .NET Core MVC](https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-6.0&tabs=visual-studio-code).
[Il est toujours possible d’appeler JavasScript via l’interface IJSRuntime](https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-6.0), ou d’avoir le code C# qui soit appelé par Javascript, si besoin.
Autres améliorations
----------------------
- **[Outils de construction .NET WebAssembly](https://docs.microsoft.com/aspnet/core/blazor/host-and-deploy/webassembly#ahead-of-time-aot-compilation)** : [Compilation anticipée](https://fr.wikipedia.org/wiki/Compilation_anticip%C3%A9e) (**A**head **O**f **T**ime), qui remplace la [compilation à la volée](https://fr.wikipedia.org/wiki/Compilation_%C3%A0_la_vol%C3%A9e) (**J**ust **I**n **T**ime) lors de l’exécution pour les applications [Blazor WebAssembly](https://docs.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-6.0), ainsi que la prise en charge des la [réédition des liens](https://fr.wikipedia.org/wiki/%C3%89dition_de_liens) du runtime .NET et des dépendances natives. [Un exemple avec Rust](https://www.youtube.com/watch?v=kesUNeBZ1Os) ([code source](https://github.com/stevesandersonms/blazeorbital)).
- **Applications monopages** : Support intégré pour [Angular](https://fr.wikipedia.org/wiki/Angular) 12 et [React](https://fr.wikipedia.org/wiki/React) 17 basé sur un modèle flexible qui peut être utilisé avec d’autres frameworks JavaScript frontaux populaires.
- **Contrôle des sockets** : Contrôle accru de la création et de la gestion des [sockets ](https://fr.wikipedia.org/wiki/Berkeley_sockets);
- **En-têtes fortement typés** : Accès aux [en-têtes](https://fr.wikipedia.org/wiki/Header) [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) d’une manière fortement typée au lieu de chaînes de caractères ;
- **Journalisation [HTTP](https://docs.microsoft.com/aspnet/core/fundamentals/http-logging) et [W3C](https://docs.microsoft.com/aspnet/core/fundamentals/w3c-logger)** : Enregistrez le trafic HTTP en utilisant le format de journal _[W3C Extended Log File Format](https://en.wikipedia.org/wiki/Extended_Log_Format)_ ;
- **[HTTP/3 (aperçu)](https://docs.microsoft.com/aspnet/core/fundamentals/servers/kestrel/http3)** : Aperçu du support serveur pour HTTP/3 basé sur le nouveau protocole de transport [QUIC](https://fr.wikipedia.org/wiki/QUIC).
Pour une liste complète de toutes les nouveautés d’ASP.NET Core dans .NET 6, consultez [les notes de publication d’ASP.NET Core dans .NET 6](https://docs.microsoft.com/fr-fr/aspnet/core/release-notes/aspnetcore-6.0?view=aspnetcore-6.0).
Performance
===========
Depuis le lancement du projet .NET Core, l’équipe s’intéresse de plus en plus aux performances (NdT: et met à disposition des outils tels que [PerfCollect](https://docs.microsoft.com/en-us/dotnet/core/diagnostics/trace-perfcollect-lttng)). [Stephen Toub](https://github.com/stephentoub) fait un travail remarquable pour rendre compte de l’évolution des performances de .NET à chaque version. Si vous n’en avez pas eu l’occasion, je vous recommande de jeter un coup d’œil à [son article sur les améliorations des performances dans .NET 6](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/) (NdT : [lien vers la série complète](https://devblogs.microsoft.com/dotnet/category/performance/)).
En voici ce que j’ai retenu ci-dessous.
Optimisation [dirigée par les profils](https://fr.wikipedia.org/wiki/Optimisation_dirig%C3%A9e_par_les_profils) dynamique
-----------
[Dynamic Profile-guided Optimization (PGO)](https://github.com/dotnet/runtime/blob/main/docs/design/features/DynamicPgo.md) peut améliorer sensiblement et de manière stable les performances d’un programme. Par exemple, PGO donne une amélioration de 26 % (510 K -> 640 K) du nombre de requêtes traitées par seconde pour le benchmark [_TechEmpower JSON "MVC"_](https://www.techempower.com/benchmarks/).
La PGO dynamique s’appuie sur la [compilation par paliers](https://devblogs.microsoft.com/dotnet/tiered-compilation-preview-in-net-core-2-1/) (_Tiered Compilation_), qui permet aux méthodes d’être d’abord compilées très rapidement (niveau 0) afin d’améliorer les performances au démarrage, puis d’être recompilées (niveau 1) avec de nombreuses optimisations une fois que la méthode s’est avérée efficace. Ce modèle permet d’instrumenter les méthodes au niveau 0 afin d’effectuer diverses observations sur l’exécution du code. Lorsque ces méthodes sont réintroduites au niveau 1, les informations recueillies à partir des exécutions du niveau 0 sont utilisées pour mieux optimiser le code du niveau 1. C’est l’essence même du mécanisme, qui s’intègre à [la compilation à la volée](https://fr.wikipedia.org/wiki/Compilation_%C3%A0_la_vol%C3%A9e).
La PGO dynamique aura des temps de démarrage légèrement plus lents que le _runtime_ par défaut, car il y a du code supplémentaire qui s’exécute dans les méthodes de niveau 0 pour observer le comportement des méthodes.
Pour activer cette fonctionnalité, définissez la variable d’environnement DOTNET_TieredPGO=1 dans l’environnement où votre application sera exécutée. Vous devez également vous assurer que _Tiered Compilation_ est activé (par défaut). _Dynamic PGO_ est _opt-in_ parce qu’il s’agit d’une technologie nouvelle et importante. Nous souhaitons que l’utilisation de cette technologie soit soumise à une période de tests et que les commentaires qui en découlent permettent de s’assurer qu’elle est entièrement testée. Nous avons fait la même chose avec la compilation par paliers. La PGO dynamique est pris en charge et est déjà utilisé en production par au moins un très grand service Microsoft. Nous vous encourageons à l’essayer.
Vous pouvez en savoir plus sur les avantages de la PGO dynamique dans le billet de blog sur les [Performance de .NET 6](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/), y compris le _microbenchmark_ suivant, qui mesure le coût d’un énumérateur [LINQ](https://fr.wikipedia.org/wiki/Language_Integrated_Query) particulier.
```csharp
private IEnumerator _source = Enumerable.Range(0, long.MaxValue).GetEnumerator();
[Benchmark]
public void MoveNext() => _source.MoveNext();
```
Voici le résultat, avec et sans.
Méthode Moyenne Taille du code
PGO Absente 1.905 ns 30 octets
PGO Activée 0.7071 ns 105 octets
C’est une différence assez importante, mais la taille du code a également augmenté, ce qui pourrait surprendre certains lecteurs. Il s’agit de la taille du code assembleur généré par le JIT, et non des allocations mémoire (même si éviter les allocations mémoire est un type d’optimisation très utilisé). Vous trouverez une bonne explication à ce sujet dans le [billet sur les performances de .NET 6](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/).
Une optimisation courante dans les implémentations PGO est le "fractionnement chaud/froid", où les sections d’une méthode fréquemment exécutées ("chaudes") sont rapprochées au début de la méthode, et les sections d’une méthode rarement exécutées ("froides") sont déplacées à la fin de la méthode. Cela permet une meilleure utilisation des caches d’instructions et minimise les chargements de code sans doute inutilisé.
Pour le contexte, [la répartition des interfaces](https://github.com/dotnet/coreclr/blob/master/Documentation/botr/virtual-stub-dispatch.md) est le type d’appel le plus coûteux dans .NET. Les appels de méthodes non virtuelles sont les plus rapides, et encore plus rapides sont les appels qui peuvent être éliminés par [_inlining_](https://fr.wikipedia.org/wiki/Extension_inline). Dans ce cas, la PGO dynamique fournit deux sites d’appel (alternatifs) pour [MoveNext](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ienumerator.movenext?view=net-6.0). Le premier – le chaud – est un appel direct à Enumerable+RangeIterator.MoveNext et l’autre – le froid – est un appel à une interface virtuelle via [IEnumerator](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerator-1?view=net-6.0). C’est une grande victoire si le code "chaud" est appelé la plupart du temps.
C’est là où la magie a lieu. Lorsque le JIT a instrumenté le code de niveau 0 pour cette méthode, il a notamment instrumenté cette répartition d’interface pour suivre le type concret de source à chaque invocation. Et le JIT a trouvé que chaque invocation était sur un type appelé Enumerable+RangeIterator, qui est une [classe privée](https://github.com/dotnet/runtime/blob/d019e70d2b7c2f7cd1137fac084dbcdc3d2e05f5/src/libraries/System.Linq/src/System/Linq/Range.cs#L31) utilisée pour implémenter Enumerable.Range à l’intérieur de l’implémentation [Enumerable](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=net-6.0). En tant que tel, pour le niveau 1, le JIT a émis une vérification pour voir si le type de source est ce Enumerable+RangeIterator : si ce n’est pas le cas, alors il saute à la section froide que nous avons précédemment mise en évidence qui effectue la répartition normale de l’interface. Mais si c’est le cas – ce qui, d’après les données de profilage, devrait être le cas la grande majorité du temps – il peut alors invoquer directement la méthode Enumerable+RangeIterator.MoveNext, non virtualisée. De plus, il a décidé qu’il était rentable d’_inliner_ cette méthode MoveNext. L’effet au final est que le code assembleur généré est un peu plus gros, mais optimisé pour le scénario exact qui devrait être le plus courant. C’est le genre de gains que nous voulions obtenir lorsque nous avons commencé à imaginer la PGO dynamique.
La PGO dynamique est évoquée de nouveau dans la section sur le compilateur juste à temps [RyuJIT](https://linuxfr.org/redaction/news/net-6-est-sorti-la-version-la-plus-rapide-a-ce-jour#toc-ryujit).
Améliorations des API d’E/S sur les fichiers
--------------------
[FileStream a été presque entièrement réécrit dans .NET 6](https://devblogs.microsoft.com/dotnet/file-io-improvements-in-dotnet-6/), en mettant l’accent sur l’amélioration des performances des entrées-sorties de fichiers asynchrones. Sous Windows, l’implémentation n’utilise plus d’API bloquantes et peut être jusqu’à plusieurs fois plus rapide ! Nous avons également apporté des améliorations à l’utilisation de la mémoire, sur toutes les plateformes. Après la première opération asynchrone (qui alloue généralement la mémoire), nous avons fait en sorte que les opérations asynchrones ne nécessitent aucune allocation ! De plus, nous avons uniformisé le comportement pour les cas limites où les implémentations Windows et Unix étaient différentes (et c’était possible).
Les améliorations de performance de cette réécriture profitent à tous les systèmes d’exploitation. Les utilisateurs de macOS et de Linux devraient également constater une amélioration significative des performances de FileStream.
Le banc d’essai suivant écrit 100 Mo dans un nouveau fichier.
```csharp
private byte[] _bytes = new byte[8_000];
[Benchmark]
public async Task Write100MBAsync()
{
using FileStream fs = new("file.txt", FileMode.Create, FileAccess.Write, FileShare.None, 1, FileOptions.Asynchronous);
for (int i = 0; i < 100_000_000 / 8_000; i++)
await fs.WriteAsync(_bytes);
}
```
Sous Windows avec un disque SSD, nous avons observé une accélération de quatre fois et une diminution de l’allocation de plus de 1 200 fois :
```cmd
Method Runtime Mean Ratio Allocated
Write100MBAsync .NET 5.0 1,308.2 ms 1.00 3,809 KB
Write100MBAsync .NET 6.0 306.8 ms 0.24 3 KB
```
Nous avons également identifié le besoin de fonctionnalités d’E/S sur les fichiers plus performantes :
- lectures et écritures simultanées ;
- E/S de type "[_scatter/gather_](https://en.wikipedia.org/wiki/Vectored_I/O)".
En conséquence, nous avons introduit de nouvelles API dans les classes System.IO.File et System.IO.RandomAccess pour ces cas.
```csharp
async Task AllOrNothingAsync(string path, IReadOnlyList> buffers)
{
using SafeFileHandle handle = File.OpenHandle(
path, FileMode.Create, FileAccess.Write, FileShare.None, FileOptions.Asynchronous,
preallocationSize: buffers.Sum(buffer => buffer.Length)); // indice pour l’OS afin de préallouer l’espace disque
await RandomAccess.WriteAsync(handle, buffers, fileOffset: 0); // sous Linux c’est un seul et unique appel système !
}
```
L’échantillon ci-dessus démontre :
- l’ouverture d’un _handle_ de fichier à l’aide de la nouvelle API File.OpenHandle ;
- une pré-affectation de l’espace disque à l’aide de la nouvelle fonctionnalité de [pré-affectation de taille](https://devblogs.microsoft.com/dotnet/file-io-improvements-in-dotnet-6/#preallocation-size) ;
- une écriture dans le fichier à l’aide de [la nouvelle API d’E/S de type _Scatter/Gather_](https://devblogs.microsoft.com/dotnet/file-io-improvements-in-dotnet-6/#scatter-gather-io).
La fonction de pré-allocation de la taille améliore les performances puisque les opérations d’écriture n’ont pas besoin d’étendre le fichier et qu’il est moins probable que le fichier soit fragmenté. Cette approche améliore la fiabilité puisque les opérations d’écriture n’échoueront plus en raison d’un manque d’espace, celui-ci ayant déjà été réservé. L’API d’E/S _Scatter/Gather_ réduit le nombre d’appels systèmes nécessaires pour écrire les données.
Vérification et casting d’interfaces plus rapides
-------------------------------------
Les performances du _casting_ d’interface ont été améliorées de 16 % à 38 %. Cette amélioration est particulièrement utile pour le [filtrage par motif](https://fr.wikipedia.org/wiki/Filtrage_par_motif) du langage C# vers et entre les interfaces.
Pour rappel, un exemple de filtrage par motif est le nouvel usage du mot-clé switch [apporté précédemment par C# 9](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/patterns3):
```csharp
public static LifeStage LifeStageAtAge(int age) => age switch
{
< 0 => LifeStage.Prenatal,
< 2 => LifeStage.Infant,
< 4 => LifeStage.Toddler,
< 6 => LifeStage.EarlyChild,
< 12 => LifeStage.MiddleChild,
< 20 => LifeStage.Adolescent,
< 40 => LifeStage.EarlyAdult,
< 65 => LifeStage.MiddleAdult,
_ => LifeStage.LateAdult,
};
```
![vérification d’interfaces plus rapide](https://user-images.githubusercontent.com/1142958/112411698-3f413600-8d15-11eb-899f-5a0450524b08.png)
Ce graphique illustre l’ampleur de l’amélioration via un banc d’essai représentatif.
L’un des principaux avantages du passage de certaines parties du moteur d’exécution de .NET de C++ à C# est qu’il réduit la [barrière à l’entrée](https://fr.wikipedia.org/wiki/Barri%C3%A8re_%C3%A0_l%27entr%C3%A9e). Cela inclut le casting d’interface, qui a été déplacé vers C# lors d’un des premiers changements apportés lors de l’élaboration de .NET 6. Beaucoup de personnes dans l’écosystème .NET maîtrisent davantage le C# comparé au C++ (et le _runtime_ utilise des modèles C++ difficiles à appréhender). Le simple fait de pouvoir lire une partie du code qui compose le moteur d’exécution est une étape importante pour développer la confiance des contributeurs et la qualité de leurs contributions sous leurs différentes formes (code, documentation, tests…).
_Le crédit de cette amélioration revient à Ben Adams._
Générateurs de code source pour System.Text.Json
----------------------------------
Nous avons ajouté un [générateur de code source](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/) pour System.Text.Json qui évite le besoin d’utiliser la [réflexion](https://fr.wikipedia.org/wiki/R%C3%A9flexion_(informatique)) et de génération de code au moment de l’exécution, et qui permet de générer un code de sérialisation optimal au moment de la construction. Les sérialiseurs sont généralement écrits avec des techniques très conservatrices parce qu’ils doivent l’être. Cependant, si vous lisez votre propre code source de sérialisation (qui utilise un sérialiseur), vous pouvez voir quels sont les choix évidents qui peuvent rendre un sérialiseur beaucoup plus optimal dans votre cas spécifique. C’est exactement ce que fait ce nouveau générateur de sources.
Outre l’amélioration des performances et la réduction de la mémoire, le générateur de sources produit un code optimal pour le découpage du code assembleur. Cela peut aider à produire des applications plus petites.
La [sérialisation](https://fr.wikipedia.org/wiki/S%C3%A9rialisation) des [POCO](https://en.wikipedia.org/wiki/Plain_old_CLR_object) est un scénario très courant. En utilisant le nouveau générateur de sources, nous observons que la sérialisation est ~1.6x plus rapide avec notre [banc d’essai](https://gist.github.com/layomia/2c236f74b250ed06e0cac5435f78e2cc).
```cmd
Method Mean StdDev Ratio
Serializer 243.1 ns 9.54 ns 1.00
SrcGenSerializer 149.3 ns 1.91 ns 0.62
```
Le benchmark de mise en cache [TechEmpower](https://github.com/TechEmpower/FrameworkBenchmarks) permet de tester la mise en cache en mémoire d’une plateforme ou d’un framework d’informations provenant d’une base de données. L’implémentation .NET du benchmark effectue la sérialisation JSON des données mises en cache afin de les envoyer comme réponse au [harnais de test](https://fr.wikipedia.org/wiki/Test_driven_development).
```cmd
Variant Requests/sec Requests
net5.0 243,000 3,669,151
net6.0 260,928 3,939,804
net6.0 + JSON source gen 364,224 5,499,468
```
Nous [observons](https://github.com/aspnet/Benchmarks/pull/1683) un gain de ~100 K requêtes par seconde (~40 % d’augmentation).
.NET 6 obtient un débit 50 % plus élevé que .NET 5 lorsqu’il est combiné avec [les améliorations de performance de MemoryCache](https://github.com/dotnet/runtime/issues/46970) !
C# 10
=====
L’un des principaux thèmes de [C# 10](https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/) est la poursuite du processus de simplification qui a débuté avec les [instructions de premier niveau](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#top-level-statements) de C# 9. Les nouvelles fonctionnalités suppriment encore plus de cérémonies de Program.cs, ce qui permet d’obtenir des programmes aussi courts qu’une seule ligne. Elles ont été inspirées par des discussions avec des personnes – étudiants, développeurs professionnels et autres – n’ayant aucune expérience préalable du C# et par l’apprentissage de ce qui fonctionne le mieux et est intuitif pour eux.
Ainsi, un Hello World en C# est désormais composé d’une seule ligne :
```csharp
Console.WriteLine("Hello World!");
```
La plupart des patrons de conception du SDK .NET ont été mis à jour pour offrir une expérience beaucoup plus simple et plus concise. Ce qui est maintenant possible avec C# 10. Nous avons entendu des commentaires selon lesquels certaines personnes n’aiment pas les nouveaux modèles parce qu’ils ne sont pas destinés aux experts, qu’ils suppriment l’orientation objet, qu’ils suppriment des concepts qu’il est important d’apprendre dès le premier jour d’apprentissage du langage C# ou qu’ils encouragent l’écriture d’un programme entier dans un seul fichier. Objectivement, aucun de ces points n’est vrai. Le nouveau modèle est tout aussi destiné et tout aussi approprié aux étudiants qu’aux développeurs professionnels. Il est cependant différent du modèle dérivé du C que nous avons connu jusqu’à .NET 6.
Il y a d’autres fonctionnalités et améliorations apportées par C# 10, y compris les [structures d’enregistrement.](https://linuxfr.org/redaction/news/net-6-est-sorti-la-version-la-plus-rapide-a-ce-jour#toc-record-structs)
Directives d’import globales
-----------------------
Les directives d’utilisation globale vous permettent de spécifier une directive d’utilisation une seule fois et de l’appliquer à chaque fichier que vous compilez.
Les exemples suivant montrent l’étendue de la syntaxe :
```csharp
global using System;
global using static System.Console;
global using Env = System.Environment;
```
Vous pouvez les ajouter dans n’importe quel fichier .cs, y compris Program.cs.
Les _usings_ implicites quant à eux sont des concepts propres [MSBuild](https://github.com/dotnet/msbuild) permettant d’ajouter automatiquement des directives globales à un projet, [selon le SDK utilisé](https://docs.microsoft.com/dotnet/core/compatibility/sdk/6.0/implicit-namespaces-rc1#new-behavior) (console, ASP .NET…). Par exemple, les _usings_ implicites disponibles pour une application console diffèrent de ceux disponibles pour une application Web.
Cette fonctionnalité n’est pas active par défaut pour les projets existants. Il faut la rajouter ainsi :
```xml
enable
```
Mais ils font déjà partie des patrons de conception. Pour plus d’informations, consultez [ce lien](https://docs.microsoft.com/dotnet/core/project-sdk/overview#implicit-using-directives).
Espaces de noms au niveau fichier
----------------------
Les espaces de noms à l’échelle du fichier vous permettent de déclarer l’espace de noms d’un fichier entier sans imbriquer le reste du contenu dans des { ... }. Un seul espace de noms est autorisé, et il doit être placé avant la déclaration de tout type.
La nouvelle syntaxe tient en une seule ligne :
```csharp
namespace MyNamespace;
class MyClass { ... } // Pas d'indentation
```
C’est une alternative à l’ancienne syntaxe :
```csharp
namespace MyNamespace
{
class MyClass { ... } // Tout est indenté
}
```
Cela est intéressant pour le cas extrêmement courant où il n’y a de toutes façons qu’un seul espace de noms par fichier.
Structures d’enregistrement
--------------
C# 9 a introduit les enregistrements comme une forme spéciale de classes orientées valeur. En C# 10, vous pouvez également déclarer des enregistrements qui sont des structs. Les structures en C# ont déjà l’égalité de valeur, mais les records structs ajoutent un opérateur == et une implémentation de IEquatable, ainsi qu’une implémentation de ToString basée sur la valeur :
```csharp
public record struct Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
```
Tout comme les classes d’enregistrement, les structures d’enregistrement peuvent être « positionnelles », ce qui signifie qu’elles ont un constructeur primaire qui déclare implicitement les membres publics correspondant aux paramètres :
```csharp
public record struct Person(string FirstName, string LastName);
```
Cependant, contrairement aux classes d’enregistrement, les membres publics implicites sont des propriétés mutables auto-implémentées. Ainsi, les structures d’enregistrement sont une histoire naturelle de croissance pour les tuples. Par exemple, si vous avez un type de retour qui est (string FirstName, string LastName) et que vous voulez le faire évoluer vers un type nommé, vous pouvez facilement déclarer l’enregistrement struct positionnel correspondant et maintenir la sémantique mutable.
Si vous voulez un enregistrement immuable avec des propriétés en lecture seule, vous pouvez déclarer l’ensemble de la structure d’enregistrement en lecture seule (comme pour les autres structures) ainsi :
```csharp
public readonly record struct Person(string FirstName, string LastName) ;
```
C# 10 prend également en charge les expressions _with_, non seulement pour les structures d’enregistrement, mais aussi pour toutes les structures, ainsi que pour les types anonymes :
```csharp
var updatedPerson = person with { FirstName = "Mary" };
```
F# 6
====
[F# 6](https://aka.ms/fsharp-6-release) a pour but de rendre F# plus simple et plus performant. Cela s’applique à la conception du langage, à la bibliothèque et aux outils. Notre objectif avec F# 6 (et au-delà) était de supprimer les cas particuliers du langage qui surprennent les utilisateurs ou qui constituent des obstacles à l’apprentissage de F#. Nous sommes très heureux d’avoir travaillé avec la communauté F# dans cet effort continu.
Rendre F# plus rapide et interopérable
---------------------------------------
La syntaxe `new task {...}` crée directement une [tâche](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-6.0) et la démarre. C’est l’une des fonctionnalités les plus importantes de F# 6, qui rend les tâches asynchrones plus simples, plus performantes et plus interopérables avec C# et d’autres langages .NET. Auparavant, pour créer des tâches .NET, il fallait utiliser [async](https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/async) {...} pour créer une tâche et invoquer Async.StartImmediateAsTask.
La fonctionnalité de `task {...}` est construite sur une fondation appelée « code pouvant être repris » ([RFC FS-1087](https://github.com/fsharp/fslang-design/discussions/455)). Le code pouvant être repris est une fonctionnalité de base, et nous prévoyons de l’utiliser pour construire d’autres machines à états asynchrones et itératives à haute performance à l’avenir.
F# 6 ajoute également d’autres fonctionnalités de performance pour les auteurs de bibliothèques, notamment [InlineIfLambda](https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0/FS-1098-inline-if-lambda.md) et des représentations non encadrées pour les modèles actifs F#. Une amélioration particulièrement significative des performances concerne la compilation des expressions de listes et de tableaux, qui sont désormais jusqu’à quatre fois plus rapides et dont le débogage est également amélioré et simplifié.
F# est plus facile à apprendre et plus uniforme
-----------------------------------------------
F# 6 permet d’utiliser la syntaxe d’indexation expr[idx]. Jusqu’à présent, F# utilisait expr.[idx] pour l’indexation. L’abandon de l’annotation du point est basé sur les commentaires répétés des nouveaux utilisateurs de F#, selon lesquels l’utilisation du point est perçue comme une divergence inutile par rapport à la pratique standard qu’ils attendent. Dans le nouveau code, nous recommandons l’utilisation systématique de la nouvelle syntaxe d’indexation expr[idx]. Nous devrions tous adopter cette syntaxe en tant que communauté.
La communauté F# a apporté des améliorations clés pour rendre le langage F# plus uniforme dans F# 6. La plus importante d’entre elles consiste à supprimer un certain nombre d’incohérences et de limitations dans les règles d’indentation de F#. Parmi les autres ajouts de conception visant à rendre F# plus uniforme, citons l’ajout de patterns _as_, permettant la création d’« opérations personnalisées surchargées » dans les expressions de calcul (utiles pour les [DSL](https://fr.wikipedia.org/wiki/Langage_d%C3%A9di%C3%A9)).
Cela permet aussi l’usage de '_' pour signifier les [éléments ignorés](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards) sur les liaisons d’utilisation et permet l’usage de %B pour le formatage binaire en sortie. La bibliothèque centrale de F# ajoute de nouvelles fonctions pour la copie et la mise à jour de listes, de tableaux et de séquences, ainsi que des fonctions intrinsèques [NativePtr](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-nativeinterop-nativeptrmodule.html) supplémentaires. Certaines fonctions héritées de F#, dépréciées depuis la version 2.0, entraînent désormais des erreurs. La plupart de ces changements mettent en conformité F# avec les usages habituels, ce qui diminue les surprises lors de l’apprentissage du langage.
F# 6 a également ajouté la prise en charge de conversions « implicites » et « dirigées par le type » supplémentaires dans F#. Cela signifie moins de changements de types (_upcasts_) explicites, et ajoute un support de première classe pour les conversions implicites. F# est également ajusté pour être mieux adapté à l’ère des bibliothèques numériques utilisant des entiers 64 bits, avec un élargissement implicite pour les entiers 32 bits vers des entiers 64 bits.
Amélioration de l’outillage F#
------------------------------
Les améliorations de l’outillage dans F# 6 facilitent le développement au quotidien. Le nouveau « débogage de [pipeline](https://docs.microsoft.com/fr-fr/dotnet/fsharp/language-reference/functions/#pipelines) » vous permet d’avancer, de définir des points d’arrêt et d’inspecter les valeurs intermédiaires pour la syntaxe de _piping_ F# input |> f1 |> f2. L’affichage de débogage des valeurs implicites a été amélioré, éliminant ainsi une source de confusion courante lors du débogage. L’outillage F# est désormais plus performant, le compilateur F# effectuant l’étape d’analyse syntaxique en parallèle. Les outils de l’IDE F# ont également été améliorés. Enfin, le _scripting_ en F# est maintenant encore plus robuste, vous permettant [d’épingler la version du SDK .NET utilisé par le biais de fichiers global.json](https://docs.microsoft.com/en-us/dotnet/core/tools/global-json?tabs=netcore3x).
Rechargement à chaud
----------
[Le rechargement à chaud](https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/) est fonctionnalité axée sur la productivité des développeurs. Elle vous permet d’apporter une grande variété de modifications au code d’une application en cours d’exécution, réduisant ainsi le temps que vous devez passer à attendre que les applications se reconstruisent, redémarrent ou reviennent au même endroit où vous étiez après avoir apporté une modification au code.
Le rechargement à chaud est disponible à la fois via l’outil dotnet watch et Visual Studio 2022. Vous pouvez utiliser Hot Reload avec une grande variété de types d’applications telles que ASP.NET Core, Blazor, .NET MAUI, Console, Windows Forms (WinForms), WPF, WinUI 3, Azure Functions, et autres.
Lorsque vous utilisez la ligne de commande, il vous suffit de lancer votre application .NET 6 à l’aide de dotnet watch, d’effectuer toute modification prise en charge et, lors de l’enregistrement du fichier (par exemple dans Visual Studio Code), ces modifications seront immédiatement appliquées. Si les modifications ne sont pas prises en charge, les détails seront enregistrés dans le terminal.
![ligne de commande hot reload](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/hot-reload-cli.png)
Cette image montre une application MVC lancée avec dotnet watch. J’ai apporté des modifications aux fichiers .cs et .cshtml (comme indiqué dans le journal) et les deux ont été appliquées au code et reflétées dans le navigateur très rapidement, en moins d’une demi-seconde.
Lorsque vous utilisez Visual Studio 2022, il vous suffit de lancer votre application, d’effectuer une modification prise en charge et d’utiliser le nouveau bouton « Hot Reload » (affiché dans l’image suivante) pour appliquer ces modifications. Vous pouvez également choisir d’appliquer les changements lors de la sauvegarde grâce au menu déroulant du même bouton. Lorsque vous utilisez Visual Studio 2022, le rechargement à chaud est disponible pour plusieurs versions de .NET, pour .NET 5+, .NET Core et .NET Framework. Par exemple, vous pourrez apporter des modifications au _code-behind_ d’un gestionnaire d’évènement OnClickEvent pour un bouton.
Le rechargement a encore quelques cas non-pris en charge, comme le point d’entrée d’une application (la méthode Main).
![Hot Reload Visual Studio 2022 experience](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/hot-reload-visual-studio-2022.png)
Note : Il existe un bogue dans RuntimeInformation.FrameworkDescription montré dans cette image qui sera corrigé très bientôt.
Le rechargement à chaud fonctionne aussi avec la fonctionnalité existante Modifier & Continuer et le rechargement à chaud pour le code XAML qui permet de modifier les interfaces graphiques en temps réel. Quant aux langages, cela fonctionne actuellement avec C# et VB .NET (mais pas F#).
Sécurité
========
La sécurité a été considérablement améliorée dans .NET 6. C’est toujours un focus important pour l’équipe, et cela comprend la modélisation des menaces, la cryptographie et les mesures de défense en profondeur.
Sous Linux, nous nous appuyons sur [OpenSSL](https://www.openssl.org/) pour toutes les opérations cryptographiques, y compris pour TLS (requis pour HTTPS). Sous macOS et Windows, nous nous appuyons sur les fonctionnalités fournies par le système d’exploitation couvrant le même besoin. Avec chaque nouvelle version de .NET, nous devons souvent ajouter la prise en charge d’une nouvelle version d’OpenSSL. .NET 6 ajoute la prise en charge d'[OpenSSL 3](https://www.openssl.org/blog/blog/2021/09/07/OpenSSL3.Final/).
Les plus grands changements d’OpenSSL 3 sont un module [FIPS 140-2](https://en.wikipedia.org/wiki/FIPS_140-2) amélioré et une licence d’utilisation plus simple.
.NET 6 exige OpenSSL 1.1 ou plus et préférera la plus haute version installée d’OpenSSL qu’il peut trouver, jusqu’à et y compris la v3. Dans le cas général, vous commencerez probablement à utiliser OpenSSL 3 lorsque la distribution Linux que vous utilisez l’adoptera par défaut. La plupart des distributions ne l’ont pas encore fait. Par exemple, si vous installez .NET 6 sur Red Hat Enterprise Linux 8 ou Ubuntu 20.04, vous ne commencerez pas (au moment de la rédaction de cet article) à utiliser OpenSSL 3.
OpenSSL 3, Windows 10 21H1 et Windows Server 2022 prennent tous en charge [ChaCha20Poly1305](https://cryptopp.com/wiki/ChaCha20Poly1305). Vous pouvez utiliser [cette nouvelle méthode de chiffrement authentifié avec .NET 6](https://github.com/dotnet/runtime/issues/45130) (si votre environnement le prend en charge).
_Merci à [Kevin Jones](https://github.com/vcsjones) pour le support Linux de ChaCha20Poly1305._
Nous avons également publié [une nouvelle feuille de route](https://github.com/dotnet/designs/blob/main/accepted/2021/runtime-security-mitigations.md) sur les mesures de sécurité des _runtime_. Il est important que le moteur d’exécution que vous utilisez soit à l’abri des attaques les plus usuelles. Nous répondons à ce besoin. Dans .NET 6, nous avons construit les premières implémentations de [W ^ X](https://fr.wikipedia.org/wiki/W%5EX) et de la technologie [Intel Control-flow enforcement (CET)](https://fr.wikipedia.org/wiki/Control-flow_integrity). W ^ X est entièrement pris en charge, activé par défaut pour macOS Arm64, et est optionnel pour les autres environnements. CET est en option et à l'état d'aperçu pour tous les environnements. Nous prévoyons que les deux technologies seront activées par défaut pour tous les environnements dans .NET 7, c’est-à-dire dès novembre 2022.
Arm64
=====
L’Arm64 suscite beaucoup d’enthousiasme en ce moment, que ce soit pour les ordinateurs portables, le matériel informatique et [d’autres appareils](https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/). Nous ressentons cette même excitation au sein de l’équipe .NET et faisons de notre mieux pour suivre cette tendance de l'industrie informatique. Nous collaborons directement avec les ingénieurs d’Arm Holdings, d’Apple et de Microsoft pour nous assurer que nos implémentations sont correctes et optimisées, et que nos plans concordent. Ces partenariats étroits nous ont beaucoup aidés.
- Nous remercions tout particulièrement Apple, qui a envoyé à notre équipe un grand nombre de kits de développement Arm64 sur lesquels travailler avant le lancement de la puce M1, et qui nous a apporté un soutien technique important ;
- Nous remercions tout particulièrement Arm Holdings, dont les ingénieurs ont revu le code de nos modifications pour Arm64 et ont également apporté des améliorations en termes de performances.
Nous avons ajouté le support initial pour Arm64 avec .NET Core 3.0 et Arm32 avant cela. L’équipe a réalisé des investissements importants pour Arm64 dans chacune des dernières versions, et cela va continuer dans un avenir proche. Dans .NET 6, nous nous sommes principalement concentrés sur la prise en charge des nouvelles puces Apple Silicon et du [cas d’usage de l’émulation x64](https://github.com/dotnet/designs/blob/main/accepted/2021/x64-emulation-on-arm64/x64-emulation.md) sur les systèmes d’exploitation macOS et Windows Arm64.
Vous pouvez installer les versions Arm64 et x64 de .NET sur les systèmes d’exploitation macOS 11+ et Windows 11+ Arm64. Nous avons dû faire plusieurs choix de conception et modifier notre logiciel pour que cela fonctionne.
Notre stratégie est de toujours privilégier l’architecture native. Nous vous recommandons de toujours utiliser le SDK qui correspond à l’architecture native, c’est-à-dire le SDK Arm64 sur macOS et Windows Arm64. Le SDK est un vaste ensemble de logiciels. Il sera beaucoup plus performant en fonctionnement natif sur une puce Arm64 qu’en émulation. Nous avons mis à jour l’invite de commandes dotnet pour rendre cela plus facile. Nous n’allons jamais nous concentrer sur l’optimisation de l’émulation x64.
Par défaut, si vous exécutez une application .NET 6 avec le SDK Arm64, elle s’exécutera en Arm64. Vous pouvez facilement passer à l’exécution en x64 avec l’argument -a, en tapant par exemple `dotnet run -a x64`. Le même argument fonctionne pour les autres verbes de l’invite de commandes. Consultez [l’article à propos de .NET 6 RC2 pour macOS et Windows Arm64](https://github.com/dotnet/sdk/issues/21686) pour plus d’informations.
Il y a là une subtilité qui doit être décrite. Lorsque vous utilisez l’argument en ligne de commande `-a x64`, le SDK s’exécute toujours de manière native en Arm64. Il existe des points prédéterminés dans l’architecture du SDK .NET où des limites sont établies sur les processus. La plupart du temps, un processus doit être entièrement [Arm64](https://en.wikipedia.org/wiki/AArch64) ou entièrement [x64](https://en.wikipedia.org/wiki/X86-64). Je simplifie un peu, mais l’invite de commandes .NET s'attend à ce que la dernière création de processus faite par le SDK et lancé par ce dernier soit créé avec l’architecture demandée, comme, par exemple, "x64". C’est dans ce dernier processus que votre code s'exécute. De cette façon, vous bénéficiez des avantages de l’architecture Arm64 en tant que développeur, mais votre code s’exécute avec l’architecture sélectionnée. **Ceci n’est pertinent que si vous avez besoin d’exécuter du code en x64**. Si ce n’est pas le cas, vous pouvez tout simplement tout exécuter en Arm64 tout le temps, et tout va pour le mieux.
Prise en charge de Arm64
-------------
Voici les points essentiels que vous devez connaître, pour macOS et Windows Arm64 :
- les SDK .NET 6 Arm64 et x64 sont pris en charge et recommandés ;
- tous les runtimes Arm64 et x64 pris en charge le sont ;
- les SDK .NET Core 3.1 et .NET 5 fonctionnent mais offrent moins de possibilités et, dans certains cas, ne sont pas entièrement pris en charge ;
- l'outil en ligne de commande dotnet test ne fonctionne pas encore correctement avec l’émulation x64. [Nous travaillons sur ce point](https://github.com/dotnet/sdk/issues/21391). dotnet test sera amélioré dans le cadre de la version 6.0.200, et peut-être même avant.
Consultez la section [Support de .NET pour macOS et Windows Arm64](https://github.com/dotnet/sdk/issues/22380) pour des informations plus complètes.
Linux est absent de cette discussion. Il ne prend pas en charge l’émulation x64 de la même manière que macOS et Windows. Par conséquent, ces nouvelles fonctionnalités en ligne de commande et l’approche de prise en charge ne s’appliquent pas directement à Linux, et Linux n’en a pas besoin.
Windows Arm64
-------------
Nous disposons d’un outil simple qui [montre l’environnement](https://www.nuget.org/packages/dotnet-runtimeinfo/) sur lequel tourne .NET appelé dotnet-runtimeinfo.
```cmd
C:Usersrich>dotnet tool install -g dotnet-runtimeinfo
You can invoke the tool using the following command: dotnet-runtimeinfo
Tool 'dotnet-runtimeinfo' (version '1.0.5') was successfully installed.
```
```
C:Usersrich>dotnet runtimeinfo
42
42 ,d ,d
42 42 42
,adPPYb,42 ,adPPYba, MM42MMM 8b,dPPYba, ,adPPYba, MM42MMM
a8" `Y42 a8" "8a 42 42P' `"8a a8P_____42 42
8b 42 8b d8 42 42 42 8PP""""""" 42
"8a, ,d42 "8a, ,a8" 42, 42 42 "8b, ,aa 42,
`"8bbdP"Y8 `"YbbdP"' "Y428 42 42 `"Ybbd8"' "Y428
**.NET information
Version: 6.0.0
FrameworkDescription: .NET 6.0.0-rtm.21522.10
Libraries version: 6.0.0-rtm.21522.10
Libraries hash: 4822e3c3aa77eb82b2fb33c9321f923cf11ddde6
**Environment information
ProcessorCount: 8
OSArchitecture: Arm64
OSDescription: Microsoft Windows 10.0.22494
OSVersion: Microsoft Windows NT 10.0.22494.0
```
Comme vous pouvez le voir, l’outil fonctionne nativement sur Windows Arm64. Voici à quoi cela ressemble avec ASP.NET Core :
![windows-arm64](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/dotnet-mvc-windows-arm64.png)
macOS Arm64
-----------
L’expérience est similaire en tous points sur macOS arm64 :
```csharp
rich@MacBook-Air app % dotnet --version
6.0.100
rich@MacBook-Air app % dotnet --info | grep RID
RID: osx-arm64
rich@MacBook-Air app % cat Program.cs
using System.Runtime.InteropServices;
using static System.Console;
WriteLine($"Hello, {RuntimeInformation.OSArchitecture} from {RuntimeInformation.FrameworkDescription}!");
rich@MacBook-Air app % dotnet run
Hello, Arm64 from .NET 6.0.0-rtm.21522.10!
rich@MacBook-Air app % dotnet run -a x64
Hello, X64 from .NET 6.0.0-rtm.21522.10!
```
Cette image montre que l’exécution en mode natif Arm64 est la valeur par défaut du SDK Arm64 et qu’il est facile de passer de l’exécution sur Arm64 à l’exécution en mode x64 en utilisant l’argument -a. L’expérience est aussi reproductible sur Windows Arm64.
![macos arm64](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/macos-arm64-x64-web.png)
Cette image montre la même chose, mais avec ASP.NET Core. Le même SDK .NET 6 Arm64 est utilisé que dans l’image précédente.
Docker sur Arm64
---------------
Docker prend en charge les conteneurs fonctionnant avec une architecture native et en émulation, l’architecture native étant la valeur par défaut. Cela semble évident mais peut être [déroutant](https://twitter.com/runfaster2000/status/1403503484226347012) lorsque la majorité du catalogue du Docker Hub est orienté x64. Vous pouvez utiliser --platform linux/amd64 pour demander une image x64.
Nous ne prenons en charge l’exécution des images de conteneurs Linux Arm64 .NET que sur les systèmes d’exploitation Arm64. En effet, nous n’avons jamais pris en charge l’exécution de .NET dans QEMU, qui est utilisé par Docker pour l’émulation d'architecture. Il semble que cela soit dû à une [limitation de QEMU] (https://github.com/dotnet/runtime/issues/13648#issuecomment-962550359).
![docker arm64](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/docker-arm64.png)
Cette image illustre l’exemple de programme [console](https://fr.wikipedia.org/wiki/Console_syst%C3%A8me) [que nous maintenons](https://github.com/microsoft/containerregistry). C’est un exemple amusant, car il contient une logique de base pour l’impression d’informations sur les limites du CPU et de la mémoire avec lesquelles vous pouvez jouer. Dans l’image, j’ai défini moi-même les limites du CPU et de la mémoire.
Essayez à votre tour :
```sh
docker run --rm mcr.microsoft.com/dotnet/samples
```
Performance Arm64
-----------------
Les projets de prise en charge de l’émulation Apple Silicon et x64 étaient très importants pour nous, mais nous avons également amélioré les performances de l’Arm64 en général.
![arm64 perfs](https://user-images.githubusercontent.com/63486087/106191399-ac927980-615f-11eb-83cf-a7647c342618.png)
Cette image montre une amélioration de la [mise à zéro du contenu de la pile des appels](https://github.com/dotnet/runtime/pull/46609), qui est une opération courante. La ligne verte représente le nouveau comportement, tandis que la ligne orange représente une autre expérience (moins avantageuse), toutes deux améliorées par rapport à la ligne de base, représentée par la ligne bleue. Pour ce test, plus c’est bas, mieux c’est.
Conteneurs
==========
.NET 6 est mieux taillé pour les conteneurs, principalement sur la base de toutes les améliorations discutées dans cet article, à la fois pour Arm64 et x64. Nous avons également apporté des changements clés qui aideront à résoudre davantage de cas d’usage. [Ce lien](https://github.com/dotnet/runtime/issues/53149) montre certaines de ces améliorations testées ensemble.
Les améliorations apportées aux conteneurs Windows et la nouvelle variable d’environnement ont également été incluses dans la mise à jour de novembre du conteneur .NET Framework 4.8, qui sortira le 9 novembre 2021.
Les notes de mise à jour sont disponibles sur nos dépôts docker :
- [notes de publication du conteneur .NET 6](https://github.com/dotnet/dotnet-docker/issues/3276) ;
- [notes de publication du conteneur .NET Framework 4.8](https://github.com/microsoft/dotnet-framework-docker/issues/849) pour Novembre 2021.
Conteneurs Windows
------------------
[.NET 6 ajoute la prise en charge des conteneurs Windows à processus isolé](https://github.com/dotnet/runtime/issues/46889). Si vous utilisez des conteneurs Windows dans [Azure Kubernetes Service](https://azure.microsoft.com/fr-fr/services/kubernetes-service/) (AKS), vous vous appuyez sur des conteneurs à processus isolé. Les conteneurs à processus isolé peuvent être considérés comme très similaires aux conteneurs Linux. Les conteneurs Linux utilisent des [cgroups](https://fr.wikipedia.org/wiki/Cgroups) et les conteneurs Windows à processus isolés utilisent des [Job Objects](https://docs.microsoft.com/en-us/windows/win32/procthread/job-objects). Windows propose également les conteneurs Hyper-V, qui offrent une plus grande isolation grâce à une plus grande virtualisation. Il n’y a pas de changement dans .NET 6 pour les conteneurs Hyper-V.
La valeur principale de ce changement est que Environment.ProcessorCount rapportera maintenant la valeur correcte avec les conteneurs Windows isolés des processus. Si vous créez un conteneur à 2 cœurs sur une machine à 64 cœurs, Environment.ProcessorCount indiquera 2. Dans les versions antérieures, cette propriété indiquait le nombre total de processeurs sur une machine, indépendamment de la limite spécifiée par l’invite de commandes de Docker, Kubernetes ou tout autre orchestrateur/exécutant de conteneurs. Cette valeur est utilisée par diverses parties de .NET à des fins de mise à l’échelle, notamment le [ramasse-miettes](https://fr.wikipedia.org/wiki/Ramasse-miettes_(informatique)) de .NET (bien qu’il s’appuie sur une API connexe plus bas niveau). Les bibliothèques communautaires s’appuient également sur cette API pour la mise à l’échelle.
Nous avons récemment validé cette nouvelle capacité avec un client, sur des conteneurs Windows en production sur AKS en utilisant un grand ensemble de [pods](https://docs.microsoft.com/fr-fr/azure/aks/concepts-clusters-workloads) Azure. Ils ont pu fonctionner avec succès avec 50 % de mémoire (par rapport à leur configuration typique), un niveau qui entraînait auparavant des exceptions OutOfMemoryException et StackOverflowException. Ils n’ont pas pris le temps de trouver la configuration de mémoire minimale, mais nous avons deviné qu’elle était nettement inférieure à 50 % de leur configuration de mémoire typique. À la suite de ce changement, ils vont passer à des configurations Azure moins chères, ce qui leur permettra de faire des économies. Il s’agit là d’un gain facile et appréciable, simplement en effectuant une mise à niveau.
Optimisation du passage à l’échelle
------------------
Des utilisateurs nous ont dit que certaines applications ne peuvent pas atteindre une mise à l’échelle optimale lorsque Environment.ProcessorCount indique la valeur correcte. Si cela ressemble à l’opposé de ce que vous venez de lire pour les conteneurs Windows, c’est un peu le cas. .NET 6 propose désormais la variable d’environnement [DOTNET_PROCESSOR_COUNT](https://github.com/dotnet/runtime/issues/48094) pour contrôler manuellement la valeur de Environment.ProcessorCount. Dans un cas d’utilisation typique, une application peut être configurée avec 4 cœurs sur une machine de 64 cœurs, et évoluer au mieux en termes de 8 ou 16 cœurs. Cette variable d’environnement peut être utilisée pour activer cette mise à l’échelle.
Ce modèle peut sembler étrange, car les valeurs de Environment.ProcessorCount et --cpus (via l’invite de commandes de Docker) peuvent différer. Les moteurs d’exécution des conteneurs, par défaut, sont orientés en termes d’équivalents de cœurs, et non de cœurs réels. Cela signifie que lorsque vous dites que vous voulez 4 cœurs, vous obtenez l’équivalent du temps CPU de 4 cœurs, mais votre application peut (en théorie) fonctionner sur beaucoup plus de cœurs, même sur les 64 cœurs d’une machine à 64 cœurs pendant une courte période. Cela pourrait permettre à votre application de mieux évoluer sur plus de 4 fils d’exécution (en continuant avec l’exemple), et allouer plus de fils d’exécution pourrait être bénéfique. Cela suppose que l’allocation des fils d’exécution est basée sur la valeur de Environment.ProcessorCount. Si vous choisissez de définir une valeur plus élevée, il est probable que votre application utilisera plus de mémoire. Pour certaines charges de travail, il s’agit d’un compromis facile. Il s’agit au moins d’une nouvelle option que vous pouvez tester.
Cette nouvelle fonctionnalité est prise en charge par les conteneurs Linux et Windows.
Docker propose également une fonction de groupes de CPU, qui permet d’affecter votre application à des cœurs spécifiques. Cette fonctionnalité n’est pas recommandée dans ce scénario, car alors le nombre de cœurs auxquels une application a accès est défini concrètement. Nous avons également constaté des problèmes lors de son utilisation avec les conteneurs Hyper-V, et elle n’est pas vraiment destinée à ce mode d’isolation.
De l’importance de Debian
====================
Nous suivons de très près [le cycle de vie et les plans de publication des distributions Linux](https://github.com/dotnet/core/labels/os-support) et essayons de faire les meilleurs choix pour vous. Debian est la distribution Linux que nous utilisons pour nos images Linux par défaut. Si vous tirez l’étiquette 6.0 de l’un de nos dépôts de conteneurs, vous tirerez une image Debian (en supposant que vous utilisez des conteneurs Linux). À chaque nouvelle version de .NET, nous nous demandons si nous devons adopter une nouvelle version de Debian.
Par principe, nous ne changeons pas la version de Debian pour nos étiquettes [git](https://fr.wikipedia.org/wiki/Git) habituelles, comme "6.0", au milieu de la phase de publication (NdT : .NET 6 a eu droit à deux _Release Candidates_). Si nous le faisions, certaines applications seraient certainement cassées. Cela signifie que le choix de la version de Debian au début de la publication est très important. De plus, ces images sont très utilisées, principalement parce qu’elles sont référencées par les « bonnes étiquettes ».
Les versions Debian et .NET ne sont naturellement pas planifiées ensemble. Lorsque nous avons commencé .NET 6, nous avons vu que la version bullseye de Debian serait probablement publiée en 2021. [Nous avons décidé de faire un pari sur bullseye dès le début de la publication](https://github.com/dotnet/dotnet-docker/pull/2582). Nous avons commencé à publier des images de conteneurs basées sur bullseye avec [.NET 6 Preview 1](https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-1/#containers) et avons décidé de ne pas regarder en arrière. Le pari était que la version finale de .NET 6 perdrait la course avec la version finale de bullseye. Le 8 août, nous ne savions toujours pas quand bullseye serait livré, ce qui laissait trois mois avant la sortie de notre propre version, le 8 novembre. Nous ne voulions pas livrer une version de production de .NET 6 sur une version préliminaire de Debian, mais nous sommes restés fermes sur le fait que nous allions perdre cette course.
Nous avons été agréablement surpris lorsque [Debian 11 "bullseye"](https://www.debian.org/News/2021/20210814) a été publiée le 14 août. Nous avons perdu la course mais gagné le pari. Cela signifie que les utilisateurs de .NET 6 obtiennent la meilleure et la plus récente Debian, par défaut, dès le premier jour. Nous pensons que Debian 11 et .NET 6 seront une excellente combinaison pour de nombreux utilisateurs. Désolé [Buster](https://www.debian.org/releases/buster/), nous avons fait [mouche](https://www.debian.org/releases/bullseye/).
Les nouvelles versions de la distribution incluent des versions majeures plus récentes de divers paquets dans leur flux de paquets et obtiennent souvent les [corrections CVE](https://security-tracker.debian.org/) plus rapidement. Cela s’ajoute à un noyau plus récent. Les utilisateurs sont mieux servis par une nouvelle version de distro.
En regardant un peu plus loin, nous allons commencer à planifier la prise en charge d'[Ubuntu 22.04](https://ubuntu.com/about/release-cycle) d’ici peu. [Ubuntu](https://ubuntu.com/) est une autre distro de la famille Debian et est populaire auprès des développeurs .NET. Nous espérons pouvoir offrir un support le jour même pour la nouvelle version Ubuntu LTS.
Chapeau à [Tianon Gravi](https://github.com/tianon) qui maintient les images Debian pour la communauté et nous aide lorsque nous avons des questions.
Dotnet monitor
==============
[dotnet monitor](https://github.com/dotnet/dotnet-monitor/tree/main/documentation) est un outil de diagnostic important pour les conteneurs. [Il est disponible en tant qu’image de conteneur](https://devblogs.microsoft.com/dotnet/whats-new-in-dotnet-monitor/) depuis un certain temps, mais dans un statut « expérimental » non pris en charge. Dans le cadre de .NET 6, nous publions [une image dotnet monitor basée sur .NET 6](https://hub.docker.com/_/microsoft-dotnet-monitor) et entièrement prise en charge en production.
[dotnet monitor est déjà utilisé par Azure App Service](https://azure.github.io/AppService/2021/11/01/Diagnostic-Tools-for-ASP-NET-Core-Linux-apps-are-now-publicly-available.html) en tant que détail de mise en œuvre de leur expérience de diagnostic ASP.NET Core Linux. C’était l’un des scénarios envisagés, qui consiste à s’appuyer sur dotnet monitor pour fournir des expériences de plus haut niveau et de plus grande valeur.
Vous pouvez télécharger l’image dès maintenant :
```sh
docker pull mcr.microsoft.com/dotnet/monitor:6.0
```
dotnet monitor facilite l’accès aux informations de diagnostic – journaux, traces, vidages de processus – d’un processus .NET. Il est facile d’accéder à toutes les informations de diagnostic que vous souhaitez sur votre ordinateur de bureau, mais ces mêmes techniques familières peuvent ne pas fonctionner en production en utilisant des conteneurs, par exemple. dotnet monitor fournit un moyen unifié de collecter ces artefacts de diagnostic, qu’ils soient exécutés sur votre ordinateur de bureau ou dans un cluster Kubernetes. Il existe deux mécanismes différents pour la collecte de ces artefacts de diagnostic :
- **Une API HTTP** pour la collecte ad-hoc d’artefacts. Vous pouvez appeler ces points de terminaison de l’API lorsque vous savez déjà que votre application rencontre un problème et que vous souhaitez recueillir davantage d’informations ;
- **Des déclencheurs** pour une configuration basée sur des règles pour une collecte permanente d’artefacts. Vous pouvez configurer des règles pour collecter des données de diagnostic lorsqu’une condition souhaitée est remplie. Par exemple, collecter un vidage de processus lorsque l’usage du CPU reste élevé.
Le moniteur dotnet fournit une API de diagnostic commune pour les applications .NET qui fonctionne partout où vous le souhaitez avec tous les outils que vous voulez. L’« API commune » n’est pas une [API .NET](https://fr.wikipedia.org/wiki/Interface_de_programmation) mais une [API Web](https://en.wikipedia.org/wiki/Web_API) que vous pouvez appeler et interroger. dotnet monitor comprend un serveur Web ASP.NET qui interagit directement avec les données d’un serveur de diagnostic dans le runtime .NET et les expose. La conception de dotnet monitor permet une surveillance de haute performance en production et une utilisation sécurisée pour contrôler l’accès aux informations privilégiées. dotnet monitor interagit avec le runtime – au-delà des limites du conteneur – via un [socket de domaine unix](https://fr.wikipedia.org/wiki/Berkeley_sockets#Socket_UNIX) non adressable par Internet. Ce modèle de communication est parfaitement adapté à ce cas d’utilisation.
Journaux JSON structurés
--------------------
À l’instar de la bibliothèque libre [Serilog](https://serilog.net/), nous avons adopté l’usage de journaux JSON structurés.
En effet, [le formateur JSON](https://docs.microsoft.com/dotnet/core/extensions/console-log-formatter#json) est désormais le _logger_ de la console par défaut dans l'[image docker ASP .NET pour .NET 6](https://hub.docker.com/_/microsoft-dotnet-aspnet). Dans .NET 5, la configuration par défaut était [le formateur de console simple](https://docs.microsoft.com/dotnet/core/extensions/console-log-formatter#simple). Ce changement a été effectué afin d’avoir une configuration par défaut qui fonctionne avec des outils automatisés qui s’appuient sur un format lisible par une machine comme le JSON.
Désormais la sortie ressemble à ce qui suit pour l’image ASP .NET :
```sh
$ docker run --rm -it -p 8000:80 mcr.microsoft.com/dotnet/samples:aspnetapp
```
```json
{"EventId":60,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository","Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","State":{"Message":"Storing keys in a directory u0027/root/.aspnet/DataProtection-Keysu0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.","path":"/root/.aspnet/DataProtection-Keys","{OriginalFormat}":"Storing keys in a directory u0027{path}u0027 that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed."}}
{"EventId":35,"LogLevel":"Warning","Category":"Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager","Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","State":{"Message":"No XML encryptor configured. Key {86cafacf-ab57-434a-b09c-66a929ae4fd7} may be persisted to storage in unencrypted form.","KeyId":"86cafacf-ab57-434a-b09c-66a929ae4fd7","{OriginalFormat}":"No XML encryptor configured. Key {KeyId:B} may be persisted to storage in unencrypted form."}}
{"EventId":14,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Now listening on: http://[::]:80","State":{"Message":"Now listening on: http://[::]:80","address":"http://[::]:80","{OriginalFormat}":"Now listening on: {address}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Application started. Press Ctrlu002BC to shut down.","State":{"Message":"Application started. Press Ctrlu002BC to shut down.","{OriginalFormat}":"Application started. Press Ctrlu002BC to shut down."}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Hosting environment: Production","State":{"Message":"Hosting environment: Production","envName":"Production","{OriginalFormat}":"Hosting environment: {envName}"}}
{"EventId":0,"LogLevel":"Information","Category":"Microsoft.Hosting.Lifetime","Message":"Content root path: /app","State":{"Message":"Content root path: /app","contentRoot":"/app","{OriginalFormat}":"Content root path: {contentRoot}"}}
```
Le type de format du journal peut être modifié en définissant ou en désactivant la variable d’environnement **Logging__Console__FormatterName** ou en modifiant le code (consultez [Formatage du journal de la console](https://docs.microsoft.com/dotnet/core/extensions/console-log-formatter) pour plus de détails).
Après l’avoir modifié, vous obtiendrez une sortie comme celle qui suit (comme dans .NET 5) :
```sh
$ docker run --rm -it -p 8000:80 -e Logging__Console__FormatterName="" mcr.microsoft.com/dotnet/samples:aspnetapp
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {8d4ddd1d-ccfc-4898-9fe1-3e7403bf23a0} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app
```
Remarque : ce changement n’affecte pas le SDK .NET sur votre machine de développement, comme ce serait le cas avec dotnet run. Cette modification est spécifique à l’image du conteneur ASP .NET.
Prise en charge des mesures OpenTelemetry
---------------------------------
Nous avons ajouté la [prise en charge d’OpenTelemetry](https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/) dans les deux dernières versions de .NET, dans le cadre de nos efforts en matière de [télémétrie](https://devblogs.microsoft.com/dotnet/conversation-about-diagnostics/). Dans .NET 6, nous ajoutons [la prise en charge](https://github.com/dotnet/runtime/issues/44445) de l’interface de programmation [OpenTelemetry Metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md). En ajoutant le support pour OpenTelemetry, vos applications peuvent interagir de manière transparente avec d’autres [systèmes OpenTelemetry](https://opentelemetry.io/).
[System.Diagnostics.Metrics](https://github.com/dotnet/designs/blob/main/accepted/2021/System.Diagnostics/Metrics-Design.md) est l’implémentation .NET de [la spécification de l’API OpenTelemetry Metrics](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md). Les API Metrics sont conçues explicitement pour traiter les mesures brutes, dans le but de produire des résumés continus de ces mesures, de manière efficace et simultanée.
Les API comprennent la classe Meter qui peut être utilisée pour créer des "instruments" de mesure. Les API comprennent quatre classes d’instruments : Counter, Histogram, ObservableCounter et ObservableGauge pour prendre en charge différents scénarios de mesure. Les API mettent à disposition également la classe MeterListener qui permet d’écouter les mesures enregistrées par l’instrument à des fins d’agrégation et de regroupement.
L’implémentation [OpenTelemetry de .NET](https://github.com/open-telemetry/opentelemetry-dotnet) sera, à terme, étendue pour utiliser ces nouvelles API.
### Exemple d’enregistrement d’une mesure
```csharp
Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");
Counter counter = meter.CreateCounter("Requests");
counter.Add(1);
counter.Add(1, KeyValuePair.Create("request", "read"));
```
### Exemple d’écoute
```csharp
MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meterListener) =>
{
if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb")
{
meterListener.EnableMeasurementEvents(instrument, null);
}
};
listener.SetMeasurementEventCallback((instrument, measurement, tags, state) =>
{
Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.Start();
```
Windows Forms
=============
Nous avons continué à apporter des améliorations clés à Windows Forms. .NET 6 comprend une meilleure accessibilité des contrôles [Win32](https://fr.wikipedia.org/wiki/Windows_API), la possibilité de définir une police par défaut pour l’ensemble de l’application, des mises à jour aux patrons de conception, etc.
Amélioration de l’accessibilité
--------------------------
Afin d’améliorer l'[accessibilité](https://fr.wikipedia.org/wiki/Accessibilit%C3%A9), nous avons ajouté des [fournisseurs](https://docs.microsoft.com/windows/win32/winauto/uiauto-providersoverview) [UI Automation](https://fr.wikipedia.org/wiki/UI_Automation) pour CheckedListBox, LinkLabel, Panel, ScrollBar, TabControl et TrackBar qui permettent à des outils comme le Narrateur et l’automatisation des tests d’interagir avec les éléments d’une application.
Police de caractères par défaut
------------
Vous pouvez maintenant [définir une police de caractère par défaut pour votre application](https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5/#application-wide-default-font) via la méthode statique _Application.SetDefaultFont_.
```csharp
void Application.SetDefaultFont(Font font)
```
Applications minimalistes
--------------------
Ce qui suit est [une application Windows Forms minimale en .NET 6](https://github.com/dotnet/designs/blob/main/accepted/2021/winforms/streamline-application-bootstrap.md):
```csharp
class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
```
À l’occasion de cette nouvelle version, nous avons mis à jour la plupart des modèles pour qu’ils soient plus modernes et minimaux, y compris pour Windows Forms. Nous avons décidé de conserver le modèle Windows Forms un peu plus traditionnel, notamment en raison de la nécessité d’appliquer l’attribut [[STAThread](https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2232?view=vs-2022)] au point d’entrée de l’application. Cependant, il y a plus en jeu qu’il n’y paraît.
(NdT: STAThread indique au runtime l'usage d'un [modèle d'isolation des fils d'exécution](https://docs.microsoft.com/en-us/windows/win32/com/single-threaded-apartments), modèle offert par Windows)
En effet, _ApplicationConfiguration.Initialize()_ est une interface de programmation générant le code source pour les appels suivants :
```csharp
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetDefaultFont(new Font(...));
Application.SetHighDpiMode(HighDpiMode.SystemAware);
```
Les paramètres de ces appels sont configurables via les [propriétés MSBuild](https://docs.microsoft.com/dotnet/core/project-sdk/msbuild-props-desktop#windows-forms-settings) dans les fichiers .csproj ou props.
Le concepteur Windows Forms dans Visual Studio 2022 est également conscient de ces propriétés (auparavant, il n'utilisait que la police par défaut), et peut vous montrer votre application telle qu’elle se présenterait au moment de l’exécution :
![bootstrap-winforms](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/windows-forms-appbootstrap.png)
Mise à jour des patrons de conception
----------------
Les patrons de conception pour les applications Windows Forms utilisant le langage C# ont été mis à jour pour prendre en charge le nouvel amorceur d’application, les directives d’utilisation globales, les espaces de noms à l’échelle du fichier et les types de référence nullables.
Davantage de concepteurs de vues
----------------------
Suite à la création des nouveaux concepteurs de vues pour [Windows Forms](https://github.com/dotnet/winforms) et [WPF](https://github.com/dotnet/wpf), vous pouvez désormais créer un concepteur polyvalent (par exemple, un concepteur de rapports), car .NET 6 possède toutes les pièces manquantes pour les concepteurs et l’infrastructure liée aux concepteurs. Pour plus d’informations, consultez [cet article de blog](https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5/#more-runtime-designers).
Applications autonomes
================
Dans .NET 6, [les applications à fichier unique en mémoire ont été activées pour Windows et macOS](https://github.com/dotnet/runtime/issues/43072). Dans .NET 5, [ce type de déploiement était limité à Linux](https://devblogs.microsoft.com/dotnet/announcing-net-5-0/#single-file-applications). Vous pouvez désormais publier un binaire à fichier unique qui est à la fois déployé et lancé comme un seul fichier, pour tous les systèmes d’exploitation pris en charge. Les applications à fichier unique [n’extraient plus la bibliothèque standard](https://github.com/dotnet/runtime/issues/43072) vers des répertoires temporaires comme c’était le cas avec .NET Core 3.1, qui a introduit les [applications autonomes](https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file).
Cette amélioration significative est basée sur un bloc de construction appelé "superhost". En .NET, L’"apphost" est l’exécutable qui lance votre application dans le cas d’une application normale, comme myapp.exe ou ./myapp. L’apphost contient le code permettant de trouver le _runtime_, de le charger et de lancer votre application avec ce _runtime_. Superhost quant à lui effectue toujours certaines de ces tâches mais utilise une copie liée statiquement de tous les binaires natifs de CoreCLR. Les applications autonomes de .NET 6 reposent désormais sur la liaison statique et non pas sur l’extraction d’une archive de la bibliothèque standard et du _runtime_.
Les dépendances natives (comme celles fournies avec un paquet [NuGet](https://www.nuget.org/)) constituent l’exception notable à l’intégration d’un fichier unique. Elles ne sont pas incluses dans le fichier unique par défaut. Par exemple, les dépendances natives de [WPF](https://fr.wikipedia.org/wiki/Windows_Presentation_Foundation) ne font pas partie du superhost, ce qui entraîne la création de fichiers supplémentaires à côté de l’application à fichier unique. Vous pouvez utiliser le paramètre _IncludeNativeLibrariesForSelfExtract_ pour intégrer et extraire les dépendances natives.
Analyse statique
---------------
Nous avons amélioré l'[analyse statique](https://fr.wikipedia.org/wiki/Analyse_statique_de_programmes) des applications à fichier unique pour permettre des avertissements personnalisés. Si vous disposez d’une API qui ne fonctionne pas dans le cadre d’une publication sur fichier unique, vous pouvez désormais la marquer avec l’attribut [RequiresAssemblyFiles], et un avertissement apparaîtra si l’analyseur est activé. L’ajout de cet attribut fera également taire tous les avertissements liés au fichier unique dans la méthode, de sorte que vous pouvez utiliser l’avertissement pour propager les avertissements vers le haut de votre [interface publique](https://fr.wikipedia.org/wiki/Interface_(programmation_orient%C3%A9e_objet)).
L’analyseur de fichier unique est automatiquement activé pour les projets exe lorsque _PublishSingleFile_ est défini sur true, mais vous pouvez également l’activer pour tout projet en définissant _EnableSingleFileAnalysis_ sur true. Ceci est utile si vous souhaitez prendre en charge une bibliothèque faisant partie d’une application à fichier unique.
Dans .NET 5, nous avions ajouté un avertissement au [compilateur](https://fr.wikipedia.org/wiki/Compilateur) pour [Assembly.Location](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location?view=net-6.0) et quelques autres interfaces de programmation qui se comportent différemment dans le contexte d'exécution des applications autonomes.
Compression
-----------
Les applications à fichier unique prennent désormais en charge la compression, qui peut être activée en définissant la propriété _EnableCompressionInSingleFile_ à _True_. Au moment de l’exécution, les fichiers sont décompressés en mémoire si nécessaire. La compression peut permettre de réaliser d’énormes économies d’espace dans certains scénarios.
Examinons la publication de fichiers uniques, avec et sans compression, sur l’application [NuGet Package Explorer](https://github.com/NuGetPackageExplorer/NuGetPackageExplorer).
Sans compression : 172 Mio
![172 Mo](https://user-images.githubusercontent.com/515774/115341581-b96eaa00-a15d-11eb-8ec2-a6739caa6da5.png)
Avec compression : 71.6 Mio
![71.6 Mo](https://user-images.githubusercontent.com/515774/115341896-39950f80-a15e-11eb-94fe-9e4c7c77118d.png)
Actuellement, la compression peut augmenter considérablement le temps de démarrage de l’application, notamment sur les plates-formes Unix. En effet le démarrage d’une application compressée sous Unix exige d’abord de la copier sur l’espace de stockage plutôt qu’en mémoire vive. Vous devez tester votre application après avoir activé la compression pour voir si le coût de démarrage supplémentaire est acceptable.
Single-file debugging
---------------------
Les applications à fichier unique ne peuvent actuellement être déboguées qu’à l’aide de débogueurs natifs, comme [WinDBG](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools). Nous envisageons d’ajouter le débogage Visual Studio dans une version ultérieure de Visual Studio 2022.
Signature des applications autonomes sur macOS
----------------------------
Les applications à fichier unique répondent désormais aux exigences d’Apple en [matière de notarisation et de signature sur macOS](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution). [Les changements spécifiques](https://github.com/dotnet/runtime/issues/3671) concernent la manière dont nous construisons les applications à fichier unique en termes de disposition discrète des fichiers.
Apple a commencé à [appliquer de nouvelles exigences](https://developer.apple.com/news/?id=09032019a) [en matière de signature et de notarisation](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution) avec [macOS Catalina](https://support.apple.com/kb/SP803). Nous avons travaillé en étroite collaboration avec Apple pour comprendre ces exigences et trouver des solutions qui permettent à une plateforme de développement comme .NET de fonctionner correctement dans cet environnement. [Nous avons apporté des modifications et documenté les flux de travail des utilisateurs](https://docs.microsoft.com/dotnet/core/install/macos-notarization-issues) afin de satisfaire aux exigences d’Apple dans chacune des dernières versions de .NET. L’une des lacunes restantes était la signature d’applications autonomes, qui est une exigence désormais satisfaite pour distribuer une application .NET sur macOS, y compris dans la boutique macOS.
Élagage du langage intermédiaire
===========
L’équipe travaille sur l’élagage de l’IL depuis plusieurs versions. .NET 6 représente une avancée majeure dans ce domaine. Nous nous sommes efforcés de produire un mode d’élagage plus agressif sûr et prévisible et avons donc décidé d’en faire le mode par défaut. _TrimMode=link_, qui était auparavant une option à activer, est désormais la valeur par défaut.
Nous avons adopté une stratégie à trois volets pour l’élagage revu et corrigé :
- Améliorer la capacité d’élagage de la plate-forme .NET ;
- Annoter la plate-forme pour fournir de meilleurs avertissements et permettre aux autres de faire de même ;
- Sur cette base, rendre le mode d’élagage par défaut plus agressif afin qu’il soit facile de réduire la taille des applications.
Le découpage était jusqu’à présent uniquement disponible sous forme de préversion, en raison du manque de fiabilité des résultats pour les applications qui comportent ou utilisent du code faisant appel à la réflexion et non annoté comme tel. Avec les avertissements d’élagage, l’expérience devrait maintenant être reproductible. Les applications sans avertissement d’élagage devraient être découpées correctement et n’observer aucun changement de comportement lors de leur exécution. Actuellement, seules les bibliothèques .NET de base ont été entièrement annotées pour l’élagage, mais nous espérons que l’écosystème adoptera cette habitude.
Diminution de la taille d’une application
-----------------------------------------
Jetons un coup d’œil à cette amélioration de l’élagage en utilisant [crossgen](https://docs.microsoft.com/dotnet/core/deploying/ready-to-run), qui est l’un des outils du SDK. Il peut être élagué avec seulement quelques avertissements, que l’équipe de crossgen a pu résoudre.
Tout d’abord, examinons la publication de l’outil crossgen en tant qu’application autonome sans élagage. Elle fait 80 Mo (ce qui inclut le runtime .NET et toutes les bibliothèques).
![publish](https://user-images.githubusercontent.com/515774/115949313-18e3f700-a489-11eb-8f2d-55aad4950bea.png)
Nous pouvons toujours essayer le mode (désormais obsolète) de .NET 5, dénommé _copyused_. Le résultat descend à 55 Mio.
![publish](https://user-images.githubusercontent.com/515774/115949175-01583e80-a488-11eb-9b2d-370e89aa1bdb.png)
Le nouveau mode d’élagage par défaut de .NET 6, dénommé _link_, réduit encore davantage la taille du fichier autonome, qui passe à 36 Mio.
![publish](https://user-images.githubusercontent.com/515774/115949349-652f3700-a489-11eb-83af-a5849c0c54bf.png)
Nous espérons que le nouveau mode d’élagage du code lors de l'[édition des liens](https://fr.wikipedia.org/wiki/%C3%89dition_de_liens) par le compilateur correspond beaucoup mieux aux attentes en la matière : économies importantes sur l’espace disque et comportement des programmes préservés.
Avertissements activés par défaut
---------------------------
Les avertissements sur l’élagage du code vous indiquent les endroits où l’élagage peut supprimer du code utilisé au moment de l’exécution. Ces avertissements étaient auparavant désactivés par défaut, car ils étaient très bruyants, en grande partie parce que la plate-forme .NET n’était pas prête pour l’élagage pas (manque d’annotations par exemple).
Nous avons annoté de grandes parties des bibliothèques .NET afin qu’elles produisent des avertissements précis. Par conséquent, nous avons estimé qu’il était temps d’activer par défaut les avertissements sur l’élagage. Les bibliothèques liées aux _runtimes_ ASP.NET Core et Windows Desktop n’ont pas été annotées. Nous prévoyons d’annoter ensuite les composants ASP .NET (après la publication de .NET 6). Nous espérons que la communauté annotera les bibliothèques NuGet tierces parties maintenant que .NET 6 est disponible.
Vous pouvez désactiver les avertissements en attribuant la valeur true à SuppressTrimAnalysisWarnings :
```xml
True
```
Plus d’informations :
- [Avertissements possibles du compilateur lors de l’élagage](https://github.com/mono/linker/blob/main/docs/fixing-warnings.md) ;
- [Introduction à l’élagage](https://docs.microsoft.com/dotnet/core/deploying/trimming/trim-self-contained) ;
- [La préparation des bibliothèques .NET pour l’élagage](https://docs.microsoft.com/dotnet/core/deploying/prepare-libraries-for-trimming).
Partagé avec Native AOT
----------------------
Nous avons également [implémenté les mêmes avertissements](https://github.com/dotnet/runtimelab/issues/248) pour l’élagage du code au sein [du projet expérimental](https://github.com/dotnet/runtime/issues/61231) de compilation native dénommé Native AOT.
Mathématiques
=============
Nous avons considérablement amélioré les API mathématiques. Certaines personnes de la communauté utilisent déjà ces améliorations avec succès.
Interfaces de programmation axées sur la performance
-------------------------
Des API mathématiques axées sur les performances ont été ajoutées à System.Math. Leur mise en œuvre est accélérée par le matériel si le matériel sous-jacent le supporte.
### Nouvelles interfaces de programmation
- [SinCos](https://docs.microsoft.com/en-us/dotnet/api/system.math.sincos?view=net-6.0) pour calculer simultanément Sin et Cos ;
- [ReciprocalEstimate](https://docs.microsoft.com/en-us/dotnet/api/system.math.ReciprocalEstimate?view=net-6.0) pour calculer une approximation de 1 / x ;
- [ReciprocalSqrtEstimate](https://docs.microsoft.com/en-us/dotnet/api/system.math.ReciprocalSqrtEstimate?view=net-6.0) pour calculer une valeur approchée de 1 / Sqrt(x).
### Nouvelles surcharges
- [Clamp](https://docs.microsoft.com/en-us/dotnet/api/system.math.clamp?view=net-6.0), [DivRem](https://docs.microsoft.com/en-us/dotnet/api/system.math.divrem?view=net-6.0), [Min](https://docs.microsoft.com/en-us/dotnet/api/system.math.min?view=net-6.0), et [Max](https://docs.microsoft.com/en-us/dotnet/api/system.math.max?view=net-6.0) prennent en charge [nint et nuint](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nint-nuint) ;
- [Abs](https://docs.microsoft.com/en-us/dotnet/api/system.math.abs?view=net-6.0) et [Sign](https://docs.microsoft.com/en-us/dotnet/api/system.math.sign?view=net-6.0) prennent en charge nint ;
- De nouvelles variantes pour [DivRem](https://docs.microsoft.com/en-us/dotnet/api/system.math.divrem?view=net-6.0) qui retournent un [Tuple](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples).
Améliorations des performances
------------------
- [ScaleB](https://docs.microsoft.com/en-us/dotnet/api/system.math.scaleb?view=net-5.0) a été réécrit en C# ce qui a amélioré les performances [jusqu’à 93 %](https://github.com/dotnet/runtime/pull/42476#issuecomment-771825502) ;
_Merci à [Alex Covington](https://github.com/alexcovington)._
### Performances sur les _BigInteger_
[L’analyse des BigIntegers](https://github.com/dotnet/runtime/pull/47842) à partir de chaînes de caractères décimales et hexadécimales a été améliorée. Nous constatons des [améliorations allant jusqu’à 89 %](https://github.com/DrewScoggins/performance-2/issues/5765), comme le montre le graphique suivant (plus la ligne est basse plus les performances sont meilleures).
![graph](https://camo.githubusercontent.com/4ebb3bde09bcf4e6217f1337fc16b4c8df80d1047ba2d18e7422f0dfce1244b2/68747470733a2f2f707673636d6475706c6f61642e626c6f622e636f72652e77696e646f77732e6e65742f6175746f66696c657265706f72742f6175746f66696c657265706f7274732f30355f31315f323032312f726566732f68656164732f6d61696e5f7836345f57696e646f777325323031302e302e31383336325f496d70726f76656d656e742f53797374656d2e4e756d65726963732e54657374732e506572665f426967496e74656765725f342e706e67)
_Merci à [Joseph Da Silva](https://github.com/jfd16)._
### Interfaces de programmation garanties sans copie
[Plusieurs interfaces de programmation de l’espace de noms System.Numerics.Complex sont désormais annotées comme _readonly_](https://github.com/dotnet/runtime/pull/51797/) afin de garantir qu’aucune copie n’est effectuée pour les valeurs _readonly_ ou les valeurs passées en paramètre.
_Merci à [hrrrrustic](https://github.com/hrrrrustic)._
BitConverter prend désormais en charge les transformations de valeurs à virgules flottantes vers des entiers non signés
---------------------------------------------------------------------
BitConverter prend en charge désormais [DoubleToUInt64Bits, HalfToUInt16Bits, SingleToUInt32Bits, UInt16BitsToHalf, UInt32BitsToSingle, and UInt64BitsToDouble](https://github.com/dotnet/runtime/pull/53784). Cela devrait faciliter la manipulation des bits à virgule flottante lorsque cela est nécessaire.
_Credit to [Michal Petryka](https://github.com/MichalPetryka)._
BitOperations prend en charge de nouvelles fonctionnalités
-----------------------------------------------
BitOperations dispose désormais des interfaces de programmation [IsPow2](https://github.com/dotnet/runtime/pull/36163), [RoundUpToPowerOf2](https://github.com/dotnet/runtime/pull/53992), et [fournit des surcharges nint/nuint pour les fonctions existantes](https://github.com/dotnet/runtime/pull/58733).
_Merci à [John Kelly](https://github.com/john-h-k), [Huo Yaoyuan](https://github.com/huoyaoyuan), and [Robin Lindner](https://github.com/deeprobin)._
Améliorations de Vector, Vector2, Vector3, et Vector4
-----------------------------------------------------
Vector prend désormais en charge les [types valeur](https://fr.wikipedia.org/wiki/Type_valeur_et_type_r%C3%A9f%C3%A9rence) [nint et nuint](https://github.com/dotnet/runtime/pull/50832), ajoutés en C# 9. Par exemple, ce changement devrait simplifier l’utilisation d’instructions SIMD avec des pointeurs ou des types de longueur dépendant de la plate-forme.
Vector prend désormais en charge [la méthode Sum](https://github.com/dotnet/runtime/pull/53527) pour simplifier le calcul de la "somme horizontale" de tous les éléments du vecteur. _Merci à [Ivan Zlatanov](https://github.com/zlatanov)._
Vector prend désormais en charge [une méthode As générique](https://github.com/dotnet/runtime/pull/47150) pour simplifier le traitement des vecteurs dans des contextes génériques où le type concret n’est pas connu. _Merci à [Huo Yaoyuan](https://github.com/huoyaoyuan)._
[Des surcharges](https://github.com/dotnet/runtime/pull/50062) prenant en charge [Span](https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay) ont été ajoutées à _Vector2_, _Vector3_ et _Vector4_ pour améliorer l’expérience lors du chargement ou du stockage des objets de type vecteur.
Meilleure analyse syntaxique des formats numériques standard
------------------------------------------
Nous avons [amélioré l’analyseur syntaxique pour les types numériques standards](https://github.com/dotnet/runtime/issues/46827), en particulier pour .ToString et .TryFormat. Ils comprennent désormais les demandes de précision > 99 décimales et fournissent des résultats précis jusqu’à ce nombre de chiffres. De plus, l’analyseur supporte mieux les zéros de fin de ligne dans la méthode Parse.
Les exemples suivants montrent le comportement avant et après.
```csharp
32.ToString("C100") -> C132
.NET 6: $32.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
.NET 5: Nous avions une limitation artificielle dans le code de formatage pour ne traiter qu'une précision de <= 99. Pour une précision >= 100, nous avons plutôt interprété l'entrée comme un format personnalisé.
32.ToString("H99") -> throw a FormatException
.NET 6: lève une exception de type FormatException
C'est le comportement attendu, mais il est appelé ici pour contraster avec l'exemple suivant.
32.ToString("H100") -> H132
.NET 6: lève une exception de type FormatException
.NET 5: H est un spécificateur de format invalide. Nous aurions donc dû lever une FormatException. Au lieu de cela, notre comportement incorrect consistant à interpréter la précision >= 100 comme des formats personnalisés nous a permis de renvoyer des valeurs erronées.
double.Parse("9007199254740997.0") -> 9007199254740998
.NET 6: 9007199254740996.
.NET 5: 9007199254740997.0 n'est pas exactement représentable dans le format IEEE 754. Avec notre schéma d'arrondi actuel, la valeur de retour correcte aurait dû être 9007199254740996. Cependant, la dernière partie .0 de l'entrée a forcé l'analyseur à arrondir incorrectement le résultat et à renvoyer 9007199254740998.
```
System.Text.Json
================
System.Text.Json fournit plusieurs API hautes performances pour le traitement des documents JSON. Au cours des dernières versions, nous avons ajouté de nouvelles fonctionnalités pour améliorer encore les performances du traitement JSON et pour faciliter la migration pour les utilisateurs de [NewtonSoft.Json](https://www.nuget.org/packages/Newtonsoft.Json). Cette version continue sur cette voie et constitue une avancée majeure en termes de performances, en particulier avec le générateur de sources du sérialiseur.
Génération de code source par JsonSerializer
--------------------------------
Remarque : les applications qui ont utilisé [la génération de sources avec .NET 6 RC1 ou des versions antérieures doivent être recompilées.](https://github.com/dotnet/core/issues/6570#issuecomment-938637761)
L’épine dorsale de presque tous les sérialiseurs .NET est la [réflexion](https://fr.wikipedia.org/wiki/R%C3%A9flexion_(informatique)). La réflexion est une excellente capacité pour certains scénarios, mais pas comme base d’applications cloud-native hautes performances (qui (dé)sérialisent et traitent généralement beaucoup de documents JSON). De part sa lenteur inhérente, la réflexion est un problème pour le temps de [démarrage](https://github.com/dotnet/runtime/issues/1568), l’utilisation de la mémoire et l'[élagage du code](https://github.com/dotnet/runtime/issues/45441).
L’alternative à la réflexion à l’exécution est la [génération de sources à la compilation](https://devblogs.microsoft.com/dotnet/new-c-source-generator-samples/). Dans .NET 6, nous incluons [un nouveau générateur de sources en tant que composant de System.Text.Json](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/). Le générateur de sources JSON fonctionne conjointement avec JsonSerializer et peut être configuré de plusieurs façons.
Il peut offrir les avantages suivants :
- Réduire le temps de démarrage ;
- Améliorer le débit de sérialisation ;
- Réduction de l’utilisation de la mémoire ;
- Suppression de l’utilisation de System.Reflection et System.Reflection.Emit au moment de l’exécution ;
- Compatibilité avec l’élagage du langage intermédiaire (IL).
Par défaut, le générateur de sources JSON émet une logique de sérialisation pour les types sérialisables donnés en entrée. Cela permet d’obtenir de meilleures performances qu’en utilisant les méthodes JsonSerializer existantes, en générant un code source qui utilise directement Utf8JsonWriter. En bref, les générateurs de sources offrent un moyen de vous donner une implémentation différente à la compilation afin d’améliorer les performances à l’exécution, et réduire la taille de votre application.
En considérant ce type utilisateur simple :
```csharp
namespace Test
{
internal class JsonMessage
{
public string Message { get; set; }
}
}
```
Le générateur de sources peut être configuré pour générer une logique de sérialisation pour les instances du type JsonMessage de l’exemple. Notez que le nom de la classe JsonContext est arbitraire. Vous pouvez utiliser le nom de classe de votre choix pour le code source générée.
```csharp
using System.Text.Json.Serialization;
namespace Test
{
[JsonSerializable(typeof(JsonMessage)]
internal partial class JsonContext : JsonSerializerContext
{
}
}
```
L’invocation du sérialiseur avec ce mode pourrait ressembler à l’exemple suivant. Cet exemple fournit les meilleures performances possibles.
```csharp
using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);
JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);
writer.Flush();
// Writer contient:
// {"Message":"Hello, world!"}
```
Le mode de génération de sources le plus rapide et le plus optimisé – basé sur [Utf8JsonWriter](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonwriter?view=net-6.0) – n’est actuellement disponible que pour la sérialisation. Un support similaire pour la désérialisation – basé sur [Utf8JsonReader](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonreader?view=net-6.0) – pourrait être fourni à l’avenir en fonction des retours.
Le générateur de sources émet également une logique d’initialisation des [métadonnées](https://fr.wikipedia.org/wiki/M%C3%A9tadonn%C3%A9e) de type qui peut également profiter à la désérialisation. Pour désérialiser une instance de JsonMessage en utilisant les métadonnées de type pré-générées, vous pouvez procéder comme suit :
```csharp
JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);
```
Prise en charge de JsonSerializer pour IAsyncEnumerable
-------------------------------------------
Vous pouvez désormais (dé)sérialiser des tableaux JSON qui peuvent être itérés de manière asynchrone au travers de l’interface [IAsyncEnumerable](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iasyncenumerable-1?view=net-5.0) avec System.Text.Json. Les exemples suivants utilisent des flux comme représentation de toute source de données asynchrone. La source peut être des fichiers sur une machine locale, ou les résultats d’une requête de base de données ou d’un appel API de service web.
JsonSerializer.SerializeAsync a été mis à jour pour reconnaître et fournir une manipulation spéciale pour les valeurs IAsyncEnumerable.
```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
static async IAsyncEnumerable PrintNumbers(int n)
{
for (int i = 0; i < n; i++) yield return i;
}
using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // Écrit sur la sortie standard {"Data":[0,1,2]}
```
Les valeurs IAsyncEnumerable sont uniquement prises en charge par les méthodes de sérialisation asynchrones. Toute tentative de sérialisation à l’aide des méthodes synchrones entraînera la levée d’une exception de type _NotSupportedException_.
La désérialisation asynchrone a nécessité une nouvelle interface de programmation qui renvoie un IAsyncEnumerable. Nous avons ajouté la méthode JsonSerializer.DeserializeAsyncEnumerable à cette fin, comme vous pouvez le constater dans l’exemple suivant :
```csharp
using System;
using System.IO;
using System.Text;
using System.Text.Json;
var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable(stream))
{
Console.WriteLine(item);
}
```
Cet exemple désérialise les éléments à la demande et peut être utile lors de la consommation de flux de données particulièrement conséquents. Il ne prend en charge que la lecture des tableaux JSON au niveau de la racine, bien que cela puisse être modifié à l’avenir en fonction des retours.
La méthode DeserializeAsync existante prend en charge nominalement IAsyncEnumerable, mais dans les limites de son interface de programmation ne permettant pas de recevoir un flux continu de données. Elle doit retourner le résultat final unitairement, comme vous pouvez le voir dans l’exemple suivant.
```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync(stream);
await foreach (int item in result.Data)
{
Console.WriteLine(item);
}
public class MyPoco
{
public IAsyncEnumerable Data { get; set; }
}
```
Dans cet exemple, le désérialiseur aura mis en mémoire tampon tout le contenu de IAsyncEnumerable avant de retourner l’objet désérialisé. En effet, le désérialiseur doit avoir consommé la totalité de la valeur JSON avant de renvoyer un résultat.
System.Text.Json : modèle objet accessible en écriture
--------------------------------------
La [fonctionnalité de DOM JSON inscriptible](https://github.com/dotnet/designs/blob/main/accepted/2020/serializer/WriteableDomAndDynamic.md) ajoute un [nouveau modèle de programmation simple et performant](https://github.com/dotnet/core/issues/6098#issuecomment-840857013) pour System.Text.Json. Cette nouvelle interface de programmation est intéressante, car elle évite d’avoir recours à des contrats de sérialisation fortement typés. Aussi, le [DOM](https://fr.wikipedia.org/wiki/Document_Object_Model) peut être changé (il est [mutable](https://en.wikipedia.org/wiki/Immutable_object)), contrairement au type [JsonDocument](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument?view=net-5.0) existant.
Cette nouvelle interface de programmation présente les avantages suivants :
- Une alternative légère à la sérialisation pour les cas où l’utilisation de types [POCO](https://en.wikipedia.org/wiki/Plain_old_CLR_object) n’est pas possible ou souhaitée, ou lorsqu’un schéma JSON n’est pas fixe et doit être inspecté ;
- Permet la modification efficace d’un sous-ensemble d’un grand arbre. Par exemple, il est possible de naviguer efficacement vers une sous-section d’un grand arbre JSON et de lire un tableau ou de désérialiser un POCO à partir de cette sous-section. [LINQ](https://fr.wikipedia.org/wiki/Language_Integrated_Query) peut également être utilisé conjointement.
L’exemple suivant démontre ce nouveau modèle de programmation :
```csharp
// Parse un objet JSON
JsonNode jNode = JsonNode.Parse("{"MyProperty":42}");
int value = (int)jNode["MyProperty"];
Debug.Assert(value == 42);
// ou
value = jNode["MyProperty"].GetValue();
Debug.Assert(value == 42);
// Parse un tableau JSON
jNode = JsonNode.Parse("[10,11,12]");
value = (int)jNode[1];
Debug.Assert(value == 11);
// ou
value = jNode[1].GetValue();
Debug.Assert(value == 11);
// Créé un nouveau JsonObject en utilisant des initialiseurs d'objets et des paramètres de tableaux.
var jObject = new JsonObject
{
["MyChildObject"] = new JsonObject
{
["MyProperty"] = "Hello",
["MyArray"] = new JsonArray(10, 11, 12)
}
};
// Obtient le JSON à partir du nouveau JsonObject
string json = jObject.ToJsonString();
Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}
// Les indexeurs pour les noms de propriétés et les éléments de tableaux
// sont pris en charge et peuvent être appelés à la chaîne.
Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue() == 11);
```
ReferenceHandler.IgnoreCycles
-----------------------------
[JsonSerializer (System.Text.Json)](https://docs.microsoft.com/dotnet/api/system.text.json.jsonserializer) prend désormais en charge la possibilité [d’ignorer les références circulaires lors de la sérialisation d’un graphe d’objets](https://github.com/dotnet/runtime/issues/40099). L’option _ReferenceHandler.IgnoreCycles_ a un comportement similaire à celui de [Newtonsoft.Json ReferenceLoopHandling.Ignore](https://www.newtonsoft.com/json/help/html/ReferenceLoopHandlingIgnore.htm). Une différence essentielle est que l’implémentation faite au sein de System.Text.Json remplace les boucles de référence par _null_ dans le JSON au lieu d’ignorer la [référence d'objet](https://fr.wikipedia.org/wiki/R%C3%A9f%C3%A9rence_(programmation)).
Vous pouvez constater le comportement de ReferenceHandler.IgnoreCycles dans l’exemple suivant. Dans ce cas, la propriété Next est sérialisée en tant que _null_ sous peine de créer une [référence circulaire](https://fr.wikipedia.org/wiki/R%C3%A9f%C3%A9rence_circulaire).
```csharp
class Node
{
public string Description { get; set; }
public object Next { get; set; }
}
void Test()
{
var node = new Node { Description = "Node 1" };
node.Next = node;
var opts = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles };
string json = JsonSerializer.Serialize(node, opts);
Console.WriteLine(json); // Écrit sur la sortie standard {"Description":"Node 1","Next":null}
}
```
Compilation à partir des sources
============
Avec la compilation à partir des sources, [vous pouvez compiler l’entièreté du kit de développement logiciel .NET sur votre propre machine à partir des sources](https://github.com/dotnet/source-build#building) à l’aide de seulement quelques lignes de commandes. C’est un projet très important pour nous.
[La compilation à partir des sources](https://github.com/dotnet/source-build) est un scénario et aussi une infrastructure sur lesquels nous avons travaillé en collaboration avec Red Hat avant même de livrer .NET Core 1.0. Plusieurs années plus tard, nous sommes sur le point de livrer une version entièrement automatisée de ce scénario. Pour les utilisateurs de .NET de [Red Hat Enterprise Linux (RHEL)](https://fr.wikipedia.org/wiki/Red_Hat_Enterprise_Linux), [cette capacité est très importante](https://www.redhat.com/en/about/development-model). Red Hat nous a communiqué que .NET est devenu une plateforme de développement importante pour son écosystème. Cool !
[La norme établie pour les distributions Linux](https://wiki.debian.org/Packaging/SourcePackage) est de construire du code source ouvert à l’aide de compilateurs et de chaînes d’outils qui font partie de l’archive de la distribution. Cela fonctionne pour le runtime .NET (écrit en C++), mais pas pour le code écrit en C#. Pour le code C#, nous utilisons un mécanisme de construction en deux étapes pour satisfaire aux exigences de la distro. C’est un peu compliqué, mais il est important de comprendre le flux.
Red Hat construit la source du SDK .NET en utilisant la construction binaire Microsoft du SDK .NET (étape n°1) pour produire une construction binaire open source pure du SDK (étape n°2). Ensuite, le même code source SDK est reconstruit à l’aide de cette nouvelle version du SDK (n°2) pour produire un SDK open source prouvé (n°3). Cette version binaire finale du SDK .NET (n° 3) est ensuite mise à la disposition des utilisateurs de RHEL. Après cela, Red Hat peut utiliser ce même SDK (n° 3) pour créer de nouvelles versions de .NET et n’a plus besoin d’utiliser le SDK de Microsoft pour créer des mises à jour mensuelles.
Ce processus peut être surprenant et déroutant. Les distributions open source doivent être construites par des outils open source. Ce modèle garantit que la version Microsoft du kit de développement logiciel n’est pas nécessaire, que ce soit intentionnellement ou par accident. L’exigence est plus haute, en tant que plate-forme de développement, pour être inclus dans une distro que la simple utilisation d’une licence compatible. Le projet de compilation à partir des sources a permis à .NET d’y répondre.
Le livrable pour la compilation des sources est un _tarball_ contenant le code source. Cette archive contient toutes les sources du kit de développement logiciel (pour une version donnée). À partir de là, Red Hat (ou une autre organisation) peut construire sa propre version du kit. La politique de Red Hat exige l’utilisation d’une chaîne d’outils construite à partir des sources pour produire un _tarball_ binaire, c’est pourquoi ils utilisent une méthode à deux passes. Mais cette méthode à deux passes n’est pas nécessaire pour la compilation des sources en elles-mêmes.
Il est courant dans l’écosystème Linux d’avoir à la fois des paquets ou des _tarballs_ sources et binaires disponibles pour un composant donné. Nous avions déjà des _tarballs_ binaires disponibles et nous avons maintenant des _tarballs_ sources également. Ainsi, .NET correspond au modèle d’un composant standard sous Linux.
La grande amélioration de .NET 6 est que l’archive source est maintenant un artefact produit par la compilation. Auparavant, sa production nécessitait un effort manuel considérable, ce qui entraînait également une latence importante dans la livraison de l’archive _tarball_ contenant les sources à Red Hat. Aucune des deux parties n’était satisfaite de cette situation.
Nous travaillons en étroite collaboration avec Red Hat sur ce projet depuis plus de cinq ans. Il a réussi, en grande partie, grâce aux efforts des excellents ingénieurs de Red Hat avec lesquels nous avons eu le plaisir de travailler. D’autres distributions et organisations ont bénéficié et bénéficieront de leurs efforts.
Par ailleurs, la compilation à partir des sources est un grand pas vers des [compilations reproductibles](https://wiki.debian.org/ReproducibleBuilds), ce à quoi nous croyons fermement. Le kit de développement logiciel .NET et le compilateur C# disposent d’importantes capacités de compilations reproductibles.
Nouvelles interfaces de programmation dans la bibliothèque standard
==============
Les interfaces de programmations suivantes ont été ajoutés, en plus de celles déjà décrites précédemment.
Compression WebSocket
---------------------
La compression est importante pour toute donnée transmise sur un réseau. [Les WebSockets permettent désormais d’utiliser la compression](https://github.com/dotnet/runtime/issues/20004). Nous avons utilisé une implémentation de l’extension [permessage-deflate](https://datatracker.ietf.org/doc/html/rfc7692#page-12) pour WebSockets, conformément à la [RFC 7692](https://tools.ietf.org/html/rfc7692). Elle permet de compresser les charges utiles des messages WebSockets en utilisant l’algorithme [DEFLATE](https://fr.wikipedia.org/wiki/Deflate). Cette [fonctionnalité](https://github.com/dotnet/runtime/issues/31088) était l’une des principales demandes des utilisateurs de Networking sur GitHub.
La compression utilisée avec le chiffrement peut conduire à des attaques, comme [CRIME](https://en.wikipedia.org/wiki/CRIME) et [BREACH](https://en.wikipedia.org/wiki/BREACH). Cela signifie qu’un secret ne peut pas être envoyé avec des données générées par l’utilisateur dans un contexte de compression unique, sinon ce secret pourrait être extrait. Pour attirer l’attention des utilisateurs sur ces implications et les aider à évaluer les risques, nous avons nommé l’une des API clés DangerousDeflateOptions. Nous avons également ajouté la possibilité de désactiver la compression pour des messages spécifiques, de sorte que si l’utilisateur souhaite envoyer un secret, il peut le faire en toute sécurité sans compression.
[L’empreinte mémoire du WebSocket lorsque la compression est désactivée](https://github.com/dotnet/runtime/pull/52022) a été réduite d’environ 27 %.
L’activation de la compression du côté client est facile, comme vous pouvez le voir dans l’exemple suivant. Cependant, n’oubliez pas que le serveur peut négocier les paramètres, par exemple en demandant une fenêtre plus petite ou en refusant complètement la compression.
```csharp
var cws = new ClientWebSocket();
cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions()
{
ClientMaxWindowBits = 10,
ServerMaxWindowBits = 10
};
```
[La prise en charge de la compression WebSocket a aussi été rajoutée à ASP .NET Core](https://github.com/dotnet/aspnetcore/issues/2715).
_Merci à [Ivan Zlatanov](https://github.com/zlatanov)._
Prise en charge des serveurs mandataires pour le protocole SOCKS
-------------------
[SOCKS](https://fr.wikipedia.org/wiki/SOCKS) est une implémentation de serveur proxy qui peut traiter tout trafic TCP ou UDP, ce qui en fait un système très polyvalent. C’est [une demande de longue date](https://github.com/dotnet/runtime/issues/17740) de la communauté qui a été [ajoutée à .NET 6](https://github.com/dotnet/runtime/pull/48883).
Cette modification ajoute la prise en charge de Socks4, Socks4a et Socks5, ce qui permet par exemple de tester les connexions externes via SSH ou de se [connecter au réseau Tor](https://en.wikipedia.org/wiki/SOCKS#Usage).
La classe WebProxy accepte désormais les schémas socks, comme vous pouvez le voir dans l’exemple suivant :
```csharp
var handler = new HttpClientHandler
{
Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);
```
_Merci à [Huo Yaoyuan](https://github.com/huoyaoyuan)._
Microsoft.Extensions.Hosting — interface de programmation _ConfigureHostOptions_
-------------------------------------------------------
Nous avons ajouté une nouvelle API _ConfigureHostOptions_ pour l’interface IHostBuilder afin de simplifier la configuration des applications (par exemple, la configuration du délai d’arrêt) :
```csharp
using HostBuilder host = new()
.ConfigureHostOptions(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
})
.Build();
host.Run();
```
Précédemment avec .NET 5, sa configuration était un peu plus compliquée :
```csharp
using HostBuilder host = new()
.ConfigureServices(services =>
{
services.Configure(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
});
})
.Build();
host.Run();
```
Microsoft.Extensions.DependencyInjection — interfaces de programmation _CreateAsyncScope_
----------------------------------------------------------------
L’interface de programmation [_CreateAsyncScope_](https://github.com/dotnet/runtime/pull/51840) a été créée pour gérer l’élimination des services IAsyncDisposable. Auparavant, vous avez peut-être remarqué que l’élimination d’un fournisseur de service IAsyncDisposable pouvait déclencher une exception de type _InvalidOperationException_.
L’exemple suivant illustre la nouvelle manière d’utiliser l’interfance, en utilisant CreateAsyncScope pour permettre une utilisation sûre de l’instruction [_using_](https://docs.microsoft.com/fr-fr/dotnet/csharp/language-reference/keywords/using-statement).
```csharp
await using (var scope = provider.CreateAsyncScope())
{
var foo = scope.ServiceProvider.GetRequiredService();
}
```
Le code suivant démontre le problème qui pouvait survenir :
```csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
await using var provider = new ServiceCollection()
.AddScoped()
.BuildServiceProvider();
// Cette ligne utilisant le mot clé using pour libérer la ressource à la fin du block peut lever InvalidOperationException
using (var scope = provider.CreateScope())
{
var foo = scope.ServiceProvider.GetRequiredService();
}
class Foo : IAsyncDisposable
{
public ValueTask DisposeAsync() => default;
}
```
Le code suivant permettait de contourner le problème. Il n’est plus nécessaire.
```csharp
var scope = provider.CreateScope();
var foo = scope.ServiceProvider.GetRequiredService();
await ((IAsyncDisposable)scope).DisposeAsync();
```
_Merci à [Martin Björkström](https://github.com/bjorkstromm)._
Microsoft.Extensions.Logging — génération de code à la compilation
------------------------------------------------------------
.NET 6 [ajoute le type _LoggerMessageAttribute_](https://github.com/dotnet/runtime/issues/52549). Cet attribut fait partie de l’espace de noms Microsoft.Extensions.Logging et, lorsqu’il est utilisé, il génère à la source des API de journalisation à haute performance, car n’utilisant pas la [réflexion](https://fr.wikipedia.org/wiki/R%C3%A9flexion_(informatique)). La prise en charge de la journalisation par génération de source est conçue pour offrir une solution de journalisation hautement utilisable et performante pour les applications .NET modernes. Le code source généré automatiquement s’appuie sur l’interface ILogger en conjonction avec la fonctionnalité LoggerMessage.Define.
Le générateur de sources est déclenché lorsque l’attribut _LoggerMessageAttribute_ est utilisé sur des méthodes de journalisation partielle. Lorsqu’il est déclenché, il peut soit générer automatiquement l’implémentation des méthodes partielles qu’il décore, soit produire des diagnostics au moment de la compilation avec des indications sur l’utilisation correcte. La solution de journalisation au moment de la compilation est généralement beaucoup plus rapide au moment de l’exécution que les approches de journalisation existantes. Elle y parvient en éliminant au maximum l’_unboxing_ (NdT : Le _boxing_ convertit un type valeur en type référence et l’_unboxing_ effectue l’opération inverse), les allocations temporaires et les copies.
Il existe des avantages par rapport à l’utilisation manuelle directe des interfaces de programmation _LoggerMessage.Define_ :
- Une syntaxe plus courte et plus simple : utilisation déclarative des attributs plutôt qu’une montagne de code sans intérêt ;
- Une expérience guidée pour les développeurs : le générateur émet des avertissements pour aider les développeurs à faire le bon choix ;
- Prise en charge d’un nombre arbitraire de paramètres de journalisation. LoggerMessage.Define prend en charge un maximum de six paramètres ;
- Prise en charge du niveau de journalisation dynamique. Ceci n’est pas possible avec LoggerMessage.Define seul.
Pour utiliser l’attribut _LoggerMessageAttribute_, la classe et la méthode appelantes doivent être partielles. Le générateur de code est déclenché au moment de la compilation et génère une implémentation de la méthode partielle.
```csharp
public static partial class Log
{
[LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Le socket vers `{hostName}` n'a pas pu être ouvert.")]
public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
}
```
Dans l’exemple précédent, la méthode permettant la journalisation est statique et le niveau de journalisation est spécifié dans la définition de l’attribut. Lorsque vous utilisez l’attribut dans un contexte statique, l’instance ILogger est requise en tant que paramètre. Vous pouvez également choisir d’utiliser l’attribut dans un contexte non statique. Pour plus d’exemples et de scénarios d’utilisation, [consultez la documentation du générateur de sources de journalisation à la compilation](https://docs.microsoft.com/dotnet/core/extensions/logger-message-generator).
Langage intégré pour les requêtes (LINQ)
----------------------------------------
Depuis longtemps la communauté étend le langage de requêtes intégré grâce à des bibliothèques libres telles que [MoreLINQ](https://github.com/morelinq/MoreLINQ).
Aujourd’hui, .NET 6 étend et améliore ce même langage.
### System.Linq — Prise en charge des énumérables pour les paramètres des méthodes _Index_ et _Range_
La méthode Enumerable.ElementAt accepte désormais les indices à partir de la fin de l’énumérable, comme vous pouvez le voir dans l’exemple suivant :
```csharp
Enumerable.Range(1, 10).ElementAt(^2); // retourne 9
```
Une surcharge Enumerable.Take a été ajoutée qui accepte les paramètres Range. Elle simplifie la prise de tranches de séquences énumérables :
```csharp
source.Take(..3) // à la place de source.Take(3)
source.Take(3..) // à la place de source.Skip(3)
source.Take(2..7) // à la place de source.Take(7).Skip(2)
source.Take(^3..) // à la place de source.TakeLast(3)
source.Take(..^3) // à la place de source.SkipLast(3)
source.Take(^7..^3) // à la place de source.TakeLast(7).SkipLast(3).
```
_Merci à [@dixin](https://github.com/dixin)._
### System.Linq — TryGetNonEnumeratedCount
La méthode TryGetNonEnumeratedCount tente d’obtenir le compte de l’énumérable source sans forcer une énumération. Cette approche peut être utile dans les scénarios où il est utile de pré-allouer des tampons avant l’énumération, comme vous pouvez le voir dans l’exemple suivant :
```csharp
List buffer = source.TryGetNonEnumeratedCount(out int count) ? new List(capacity: count) : new List();
foreach (T item in source)
{
buffer.Add(item);
}
```
TryGetNonEnumeratedCount vérifie les sources implémentant ICollection/ICollection ou [tire parti de certaines des optimisations internes utilisées par Linq](https://github.com/dotnet/runtime/blob/a123d28793ad22954ca6d9074f43b540d0d30b43/src/libraries/System.Linq/src/System/Linq/IIListProvider.cs).
### System.Linq — DistinctBy/UnionBy/IntersectBy/ExceptBy
De nouvelles variantes ont été ajoutées aux opérations de set qui permettent de spécifier l’égalité à l’aide de fonctions de sélection de clés, comme vous pouvez le voir dans l’exemple suivant :
```csharp
Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}
var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }
```
### System.Linq — MaxBy/MinBy
Les méthodes MaxBy et MinBy permettent de trouver les éléments maximaux ou minimaux à l’aide d’un sélecteur de clé, comme vous pouvez le voir dans l’exemple suivant :
```csharp
var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age); // ("Ashley", 40)
```
### System.Linq — Chunk
Chunk peut être utilisé pour découper un énumérable source en tranches d’une taille fixe, comme vous pouvez le voir dans l’exemple suivant :
```csharp
IEnumerable chunks = Enumerable.Range(0, 10).Chunk(size: 3); // { {0,1,2}, {3,4,5}, {6,7,8}, {9} }
```
_Merci à [Robert Andersson](https://github.com/inputfalken)._
### System.Linq — FirstOrDefault/LastOrDefault/SingleOrDefault surcharges prenant des paramètres par défaut
Les méthodes existantes FirstOrDefault/LastOrDefault/SingleOrDefault retournent [default(T)](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default) si l’énumérable source est vide. De nouvelles surcharges ont été ajoutées qui acceptent qu’un paramètre par défaut soit retourné dans ce cas, comme vous pouvez le voir dans l’exemple suivant.
```csharp
Enumerable.Empty().SingleOrDefault(-1); // retourne -1
```
_Merci à [@Foxtrek64](https://github.com/Foxtrek64)._
### System.Linq — Nouvelle surcharge prenant en paramètres trois énumérables
La méthode [Zip](https://docs.microsoft.com/dotnet/api/system.linq.enumerable.zip) permet désormais de combiner trois énumérables, comme vous pouvez le voir dans l’exemple suivant :
```csharp
var xs = Enumerable.Range(1, 10);
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);
foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs))
{
}
```
_Merci à [Huo Yaoyuan](https://github.com/huoyaoyuan)._
La nouvelle collection générique _PriorityQueue_
-------------
[PriorityQueue](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.priorityqueue-2?view=net-6.0) (dans l’espace de noms System.Collections.Generic) est une [nouvelle collection](https://github.com/dotnet/runtime/pull/46009) [générique](https://fr.wikipedia.org/wiki/G%C3%A9n%C3%A9ricit%C3%A9) qui permet d’ajouter de nouveaux éléments avec une valeur et une priorité. À la sortie de la file d’attente, la PriorityQueue renvoie l’élément avec la valeur de priorité la plus basse. Vous pouvez considérer cette nouvelle collection comme similaire à [Queue](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=net-5.0), mais chaque élément mis en file d’attente a une valeur de priorité qui affecte le comportement de la méthode Dequeue.
Le code suivant démontre le comportement de la PriorityQueue.
```csharp
// créé une PriorityQueue à l'aide de nombres entiers
var pq = new PriorityQueue();
// Ajoute des éléments et de leurs priorité associée
pq.Enqueue("A", 3);
pq.Enqueue("B", 1);
pq.Enqueue("C", 2);
pq.Enqueue("D", 3);
pq.Dequeue(); // returns "B"
pq.Dequeue(); // returns "C"
pq.Dequeue(); // soit "A" ou "D", la prédictibilité dans ce cas n'est pas garantie.
```
_Merci à [Patryk Golebiowski](https://github.com/pgolebiowski)._
Amélioration des performances pour les dictionnaires utilisant des structs en tant que clés
-----------------------------------------------
[CollectionsMarshal.GetValueRef](https://github.com/dotnet/runtime/pull/49388) est une nouvelle interface de programmation [**utilisant des pointeurs mémoire**](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code) qui accélère la mise à jour des valeurs de structure dans les dictionnaires. Cette nouvelle interface de programmation est destinée à des scénarios de haute performance et non à un usage général. Elle renvoie une référence à la valeur de la structure, qui peut ensuite être mise à jour sur place avec les techniques habituelles.
Le code suivant démontre l’utilisation de l’interface de programmation :
```csharp
ref MyStruct value = CollectionsMarshal.GetValueRef(dictionary, key);
// Retourne Unsafe.NullRef() s'il n'existe pas; Vérifiable en utilisant Unsafe.IsNullRef(ref value)
if (!Unsafe.IsNullRef(ref value))
{
// Mutation de la valeur sur place
value.MyInt++;
}
```
Avant cette modification, la mise à jour des valeurs des dictionnaires de structure pouvait s’avérer coûteuse pour les scénarios à hautes performances (par exemple, les programmes s’exécutant sur des [Superordinateurs](https://fr.wikipedia.org/wiki/Superordinateur)), car elle nécessitait une consultation du dictionnaire et une copie de la structure dans la [pile](https://fr.wikipedia.org/wiki/Pile_d%27ex%C3%A9cution). Puis, après avoir modifié la structure, celle-ci était à nouveau affectée à la clé du dictionnaire, ce qui entraînait une autre opération de consultation et de copie. Cette amélioration réduit le hachage de la clé à une opération (au lieu de deux) et supprime toutes les opérations de copie de la structure.
_Merci à [Ben Adams](https://github.com/benaadams)._
Nouvelles structures DateOnly et TimeOnly
---------------------------------
Elles [présentent](https://github.com/dotnet/runtime/issues/49036) les caractéristiques suivantes :
- Chacun représente la moitié d’un DateTime, soit uniquement la partie date, soit uniquement la partie heure ;
- DateOnly est idéal pour les anniversaires, les jours de fête et les jours ouvrables. Il s’aligne sur le type de date de SQL Server ;
- TimeOnly est idéal pour les réunions récurrentes, les réveils et les heures de bureau hebdomadaires. Il s’aligne sur le type d’heure de SQL Server ;
- Complète les types de date/heure existants (DateTime, DateTimeOffset, TimeSpan, TimeZoneInfo) ;
- Elles sont dans l’espace de noms System, livrés avec la bibliothèque standard, tout comme les types connexes existants.
Améliorations des performances de DateTime.UtcNow
-------------------------------------------------
Cette [amélioration](https://github.com/dotnet/runtime/pull/50263) présente les avantages suivants :
- Correction d’une régression qui [amenait 2,5 fois plus de temps d’attente](https://github.com/dotnet/runtime/issues/13091) pour l’obtention de l’heure système sous Windows ;
- Utilisation d'[une mémoire cache logicielle](https://fr.wikipedia.org/wiki/M%C3%A9moire_cache) glissante sur 5 minutes pour les données concernant les [secondes intercalaires](https://fr.wikipedia.org/wiki/Seconde_intercalaire) sous Windows au lieu de les récupérer à chaque appel.
Prise en charge à la fois des fuseaux horaires Windows et IANA sur toutes les plateformes
-------------------------------------------------------------
Les améliorations sont les suivantes :
- Conversion implicite lors de l’utilisation de TimeZoneInfo.FindSystemTimeZoneById (https://github.com/dotnet/runtime/pull/49412) ;
- Conversion explicite par le biais de nouvelles API sur TimeZoneInfo : TryConvertIanaIdToWindowsId, TryConvertWindowsIdToIanaId, et HasIanaId (https://github.com/dotnet/runtime/issues/49407) ;
- Améliore la prise en charge multiplateforme et l’interopérabilité entre les systèmes qui utilisent différents types de fuseaux horaires ;
- Supprime la nécessité d’utiliser la bibliothèque libre [TimeZoneConverter](https://github.com/mattjohnsonpint/TimeZoneConverter). La fonctionnalité est maintenant intégrée.
Noms d’affichage des fuseaux horaires améliorés
--------------------------------
Pour les systèmes d’exploitation [Unix](https://fr.wikipedia.org/wiki/Unix) et apparentés, l’affichage des fuseaux horaires [a été amélioré](https://github.com/dotnet/runtime/pull/48931):
- Supprime l’ambiguïté des noms d’affichage dans la liste renvoyée par TimeZoneInfo.GetSystemTimeZones ;
- Prend avantage des données de mondialisation de l'[ICU](https://fr.wikipedia.org/wiki/International_Components_for_Unicode) / [CLDR](https://fr.wikipedia.org/wiki/Common_Locale_Data_Repository). Pour Unix et apparentés seulement pour le moment. Windows utilise toujours les données du la [Base de Registre](https://fr.wikipedia.org/wiki/Base_de_registre). Cela pourra être modifié ultérieurement.
Les changements suivants ont aussi été apportés :
- Le nom d’affichage et le nom standard du fuseau horaire UTC étaient "codés en dur" en anglais et utilise maintenant la même langue que le reste des données du fuseau horaire (CurrentUICulture sur Unix, langue par défaut du système d’exploitation sur Windows) ;
- Les noms d’affichage des fuseaux horaires sous [Wasm](https://fr.wikipedia.org/wiki/WebAssembly) utilisent l'[ID](https://www.wikidata.org/wiki/Property:P6687) [IANA](https://fr.wikipedia.org/wiki/Internet_Assigned_Numbers_Authority) non localisé à la place, en raison des limitations de longueur des noms ;
- La classe imbriquée TimeZoneInfo.AdjustmentRule voit sa propriété interne BaseUtcOffsetDelta rendue publique et obtient un nouveau constructeur qui prend baseUtcOffsetDelta comme paramètre. (https://github.com/dotnet/runtime/issues/50256) ;
- TimeZoneInfo.AdjustmentRule reçoit également diverses corrections pour le chargement des fuseaux horaires sous Unix (https://github.com/dotnet/runtime/pull/49733), (https://github.com/dotnet/runtime/pull/50131).
Prise en charge améliorée des ACL de Windows
---------------------------------
[System.Threading.AccessControl](https://www.nuget.org/packages/System.Threading.AccessControl/) comprend désormais [une prise en charge améliorée de l’interaction avec les listes de contrôle d’accès](https://github.com/dotnet/runtime/pull/43134/) ([ACLs](https://fr.wikipedia.org/wiki/Access_Control_List)) de Windows. De nouvelles surcharges ont été ajoutées aux méthodes OpenExisting et TryOpenExisting pour EventWaitHandle, Mutex et Semaphore. Ces surcharges – à l’aide d’instances de classes apportant des "privilèges de sécurité" – permettent d’ouvrir des instances existantes d’objets de synchronisation de fils d’exécution qui ont été créés avec des attributs de sécurité spécifiques à Windows.
Cette mise à jour correspond aux API disponibles dans le .NET Framework et présente le même comportement.
Les exemples suivants démontrent l’utilisation de ces nouvelles interfaces de programmation :
Via une [_Mutex_](https://fr.wikipedia.org/wiki/Exclusion_mutuelle)
```csharp
var rights = MutexRights.FullControl;
string mutexName = "MyMutexName";
var security = new MutexSecurity();
SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
MutexAccessRule accessRule = new MutexAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);
// createdMutex, openedMutex1 et openedMutex2 pointent vers la même mutex
Mutex createdMutex = MutexAcl.Create(initiallyOwned: true, mutexName, out bool createdNew, security);
Mutex openedMutex1 = MutexAcl.OpenExisting(mutexName, rights);
MutexAcl.TryOpenExisting(mutexName, rights, out Mutex openedMutex2);
```
Via une [_Semaphore_](https://fr.wikipedia.org/wiki/S%C3%A9maphore_(informatique))
```csharp
var rights = SemaphoreRights.FullControl;
string semaphoreName = "MySemaphoreName";
var security = new SemaphoreSecurity();
SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
SemaphoreAccessRule accessRule = new SemaphoreAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);
// createdSemaphore, openedSemaphore1 et openedSemaphore2 point pointent vers la même sémaphore
Semaphore createdSemaphore = SemaphoreAcl.Create(initialCount: 1, maximumCount: 3, semaphoreName, out bool createdNew, security);
Semaphore openedSemaphore1 = SemaphoreAcl.OpenExisting(semaphoreName, rights);
SemaphoreAcl.TryOpenExisting(semaphoreName, rights, out Semaphore openedSemaphore2);
```
Via [_EventWaitHandle_](https://docs.microsoft.com/en-us/dotnet/api/system.threading.eventwaithandle?view=net-5.0)
```csharp
var rights = EventWaitHandleRights.FullControl;
string eventWaitHandleName = "MyEventWaitHandleName";
var security = new EventWaitHandleSecurity();
SecurityIdentifier identity = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
EventWaitHandleAccessRule accessRule = new EventWaitHandleAccessRule(identity, rights, AccessControlType.Allow);
security.AddAccessRule(accessRule);
// createdHandle, openedHandle1 et openedHandle2 pointent vers le même EventWaitHandle
EventWaitHandle createdHandle = EventWaitHandleAcl.Create(initialState: true, EventResetMode.AutoReset, eventWaitHandleName, out bool createdNew, security);
EventWaitHandle openedHandle1 = EventWaitHandleAcl.OpenExisting(eventWaitHandleName, rights);
EventWaitHandleAcl.TryOpenExisting(eventWaitHandleName, rights, out EventWaitHandle openedHandle2);
```
Génération de codes d’authentification de messages en un seul appel
---------------------
Les classes [HMAC](https://fr.wikipedia.org/wiki/HMAC) de [System.Security.Cryptography](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography?view=net-5.0) ont maintenant des [méthodes statiques qui permettent le calcul en une seule fois](https://github.com/dotnet/core/issues/6569#issuecomment-913876347) des HMAC sans allocations mémoire. Ces ajouts sont similaires aux [méthodes de génération de hachage](https://github.com/dotnet/runtime/issues/17590) en une seule fois qui ont été ajoutées dans une version précédente.
DependentHandle est disponible pour le code utilisateur
-----------------------------
Le type [DependantHandle](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.dependenthandle?view=net-6.0) n’est plus exclusif au cœur de .NET, mais disponible pour tous. Il permet l’usage de [l’interface de programmation suivante](https://github.com/dotnet/runtime/pull/54246) :
```csharp
namespace System.Runtime
{
public struct DependentHandle : IDisposable
{
public DependentHandle(object? target, object? dependent);
public bool IsAllocated { get; }
public object? Target { get; set; }
public object? Dependent { get; set; }
public (object? Target, object? Dependent) TargetAndDependent { get; }
public void Dispose();
}
}
```
Il peut être utilisé pour créer des systèmes avancés, tels que des systèmes de mise en cache sophistiqués ou des versions personnalisées du type [ConditionalWeakTable](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2?view=net-5.0). Par exemple, il sera utilisé par le type [WeakReferenceMessenger](https://docs.microsoft.com/dotnet/api/microsoft.toolkit.mvvm.Messaging.WeakReferenceMessenger) du [MVVM Toolkit](https://aka.ms/mvvmtoolkit/docs) pour éviter les allocations mémoire lors de la diffusion de messages.
Un thread pool réécrit
----------------------
Le [thread pool](https://docs.microsoft.com/en-us/dotnet/standard/threading/the-managed-thread-pool) de [.NET a été entièrement réécrit en C# au lieu de C++](https://github.com/dotnet/runtime/pull/38225) et est maintenant utilisé comme pool de threads par défaut dans .NET 6. Nous avons effectué ce changement pour permettre à toutes les applications .NET d’avoir accès à la même implémentation, indépendamment de l’utilisation de CoreCLR, [Mono](https://fr.wikipedia.org/wiki/Mono_(logiciel)) ou de tout autre _runtime_. Nous n’avons pas observé et ne prévoyons aucune mauvaise conséquence fonctionnelle ou de performance suite à ce changement.
RyuJIT
======
Dans cette version, l’équipe a apporté de nombreuses améliorations au compilateur .NET à la volée (JIT). documentées dans [chacun des messages](https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-5/) [de publication](https://github.com/dotnet/runtime/pull/55614) des [préversions](https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/). La plupart de ces changements améliorent les performances. Quelques-uns des points forts à propos de [RyuJIT](https://devblogs.microsoft.com/dotnet/the-ryujit-transition-is-complete/) sont documentés ci-dessous.
PGO dynamique
-------------
Dans .NET 6, nous avons activé deux formes de PGO (_Profile Guided Optimization_) :
- PGO dynamique utilise les données recueillies à partir de l’exécution en cours pour optimiser l’exécution en cours.
- La PGO statique s’appuie sur les données recueillies lors des exécutions précédentes pour optimiser les exécutions futures.
La PGO dynamique a déjà été abordée dans la section sur les performances, plus haut dans ce billet.
En résumé, la PGO dynamique permet au JIT de recueillir des informations au moment de l’exécution sur les chemins et les types de code qui sont effectivement utilisés pour cette exécution spécifique de l’application. Le JIT peut alors optimiser le code en fonction de ces chemins de code pour une amélioration parfois très significative des performances. Nous avons constaté des améliorations à deux chiffres tant en test qu’en production. Il existe un ensemble de techniques de compilation classiques qui ne sont possibles ni avec un JIT ni avec la compilation en avance sur le temps sans PGO. Nous sommes maintenant en mesure d’appliquer ces techniques. Le fractionnement chaud/froid est l’une de ces techniques et la dévirtualisation en est une autre.
Pour activer la PGO dynamique, définissez DOTNET_TieredPGO=1 dans l’environnement où votre application sera exécutée.
Comme indiqué dans la section sur les performances, la PGO dynamique permet une amélioration de 26 % (510 K -> 640 K) des demandes par seconde traitées pour la suite de bancs d’essais _TechEmpower JSON "MVC"_. C’est une amélioration importante, apportée sans aucune modification du code utilisateur.
Notre ambition est d’activer la PGO dynamique par défaut dans une prochaine version de .NET, probablement lors de la publication de .NET 7. Nous vous encourageons vivement à essayer cette fonctionnalité dans vos applications et à nous faire part de vos commentaires.
L’optimisation dynamique complète
---------------
Pour bénéficier de tous les avantages de la PGO dynamique, vous pouvez définir deux variables d’environnement supplémentaires : DOTNET_TC_QuickJitForLoops=1 et DOTNET_ReadyToRun=0. Cela permet de s’assurer qu’autant de méthodes que possible participent à la compilation par étage (_[Tiered Compilation](https://devblogs.microsoft.com/dotnet/tiered-compilation-preview-in-net-core-2-1/)_). Nous appelons cette variante 'PGO complète'. La PGO complète peut fournir de plus grands avantages en termes de performance en régime permanent que Dynamic PGO mais aura des temps de démarrage plus lents (puisque plus de méthodes doivent être compilées par le JIT au niveau 0).
Vous ne voudrez pas utiliser cette option pour une [application _serverless_](https://www.redhat.com/fr/topics/cloud-native-apps/what-is-serverless) dont le temps d’exécution est court, mais elle peut être utile pour une application avec un temps d’exécution long.
Dans les prochaines versions, nous prévoyons de rationaliser et de simplifier ces options afin que vous puissiez bénéficier des avantages de la PGO complète plus simplement et pour un plus grand nombre de cas d’usage.
La PGO statique
------------
Nous utilisons actuellement la PGO statique pour [optimiser les assemblages de bibliothèques .NET](https://fr.wikipedia.org/wiki/Base_Class_Library) tels que System.Private.CoreLib qui sont livrés avec R2R (_Ready To Run_).
L’avantage de la PGO statique est que les optimisations sont effectuées lorsque les assemblages sont compilés au format R2R avec crossgen. Cela signifie qu’il y a un bénéfice à l’exécution sans coût supplémentaire induit lors de l’exécution de l’application. C’est très significatif pour les performances, et c’est la raison pour laquelle l’optimisation guidée par les profils est importante dans d’autres langages (comme [en C++](https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html), par exemple).
Alignement des boucles
----------------------
L’alignement de la mémoire est une exigence courante pour diverses opérations dans l’informatique moderne. Dans .NET 5, nous avons [commencé à aligner les méthodes à la limite des 32 octets](https://github.com/dotnet/runtime/pull/42909). Dans .NET 6, nous avons ajouté une fonction [d’alignement adaptatif des boucles](https://devblogs.microsoft.com/dotnet/loop-alignment-in-net-6/) qui ajoute des instructions de remplissage NOP dans une méthode comportant des boucles, de sorte que le code de la boucle commence à l’adresse mémoire mod(16) ou mod(32). Ces modifications améliorent et stabilisent les performances du code .NET.
Dans le tableau de tri à bulles suivant, le point de données 1 représente le point où nous avons commencé à aligner les méthodes sur la limite de 32 octets. Le point de données 2 représente le point où nous avons commencé à aligner les boucles internes de la même manière. Comme vous pouvez le constater, les performances et la stabilité du banc d’essai s’améliorent considérablement.
![bubble sort chart](https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2021/11/stable-bubble.png)
Structures de données accélérées par le matériel
----------------------------
Les structures sont une partie importante du [système de types](https://fr.wikipedia.org/wiki/Type_(informatique)) du [CLR](https://fr.wikipedia.org/wiki/Common_Language_Runtime). Ces dernières années, ils ont été fréquemment utilisés comme primitifs de performance dans les bibliothèques .NET. Les exemples récents sont [ValueTask](https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/), [ValueTuple](https://devblogs.microsoft.com/premier-developer/dissecting-the-tuples-in-c-7/) et [Span](https://devblogs.microsoft.com/dotnet/welcome-to-c-7-2-and-span/). Les structs d’enregistrement en sont un nouvel exemple. Dans .NET 5 et .NET 6, nous avons amélioré les performances des structs, en partie en veillant à ce que les structs puissent être [maintenus dans des registres ultra-rapides](https://github.com/dotnet/runtime/issues/43867) du CPU lorsqu’ils sont des locaux, des arguments ou des valeurs de retour de méthodes). Ceci est particulièrement bénéfique pour les API qui utilisent des vecteurs pour leurs calculs.
Stabiliser les mesures de performance
-------------------------------------
L’équipe effectue une quantité énorme de travail sur les systèmes d’ingénierie qui n’apparaît jamais sur le blog. Cela est vrai pour tout produit matériel ou logiciel que vous utilisez. L’équipe JIT a entrepris un projet visant à [stabiliser les mesures de performance](https://github.com/dotnet/runtime/issues/43227) dans le but d’accroître la valeur des régressions signalées automatiquement par l’automatisation de notre laboratoire de performance interne. Ce projet est intéressant en raison de [l’enquête approfondie](https://github.com/dotnet/runtime/issues/43227) et des [changements](https://github.com/dotnet/runtime/pull/44370) qui ont été nécessaires pour permettre la stabilité. Il démontre également l’échelle à laquelle nous mesurons pour maintenir et améliorer les performances.
![performances améliorées](https://user-images.githubusercontent.com/63486087/106191620-f8452300-615f-11eb-934d-e00495992f1d.png)
Cette image montre des mesures de performance instables où la performance a fluctué entre le lent et le rapide lors de passages successifs. L’axe des x est la date du test et l’axe des y est le temps du test en nanosecondes. À la fin du graphique (après que ces changements aient été effectués), vous pouvez voir que les mesures se sont stabilisées, avec le meilleur résultat. Cette image montre un seul test. Il y a beaucoup d’autres tests qui ont un comportement similaire à l’adresse suivante [dotnet/runtime #43227](https://github.com/dotnet/runtime/issues/43227).
Code _Ready-to-run_ (R2R) / Crossgen 2
------------------------------
Lorsque vous créez un programme (ou _assembly_ en anglais) .NET à l’aide du compilateur C#, votre assemblage ne contient que du code en langage intermédiaire (MSIL, ou IL). Lorsque l’application s’exécute, le compilateur Juste à Temps traduit le code MSIL en code natif, avant que le processeur central ne puisse les exécuter. Ce modèle d’exécution présente certains avantages. Par exemple, votre code d’assemblage peut être portable sur toutes les plates-formes et architectures qui prennent en charge .NET. Toutefois, cette portabilité a un coût en termes de performances. Votre application démarre plus lentement, car le compilateur JIT doit passer du temps à traduire le code.
Pour accélérer le démarrage de votre application, [CoreCLR](https://github.com/dotnet/coreclr) (le _runtime_ de .NET) comprend un outil appelé [CrossGen](https://github.com/dotnet/runtime/blob/main/docs/workflow/building/coreclr/crossgen.md), qui peut précompiler le code intermédiaire en code natif.
[Crossgen2](https://devblogs.microsoft.com/dotnet/conversation-about-crossgen2/) est un remplacement de l’outil crossgen. Il est destiné à satisfaire deux objectifs :
- Rendre le développement de crossgen plus efficace ;
- Rendre possible un ensemble de capacités qui ne sont pas actuellement possibles avec crossgen.
Cette transition est quelque peu similaire au passage du code natif produit par l’ancien compilateur C# ([csc.exe](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/)) de [.NET Framework](https://fr.wikipedia.org/wiki/.NET_Framework) au [code managé](https://fr.wikipedia.org/wiki/Managed_code) du compilateur [Roslyn](https://github.com/dotnet/roslyn). Crossgen2 est lui aussi écrit en C#, mais il n’expose pas une API sophistiquée comme le fait Roslyn.
Il y a peut-être une demi-douzaine de projets que nous avions/avons planifiés pour .NET 6 et 7 qui dépendent de Crossgen2. La [_Pull Request_ pour les instructions vectorielles par défaut](https://github.com/dotnet/designs/pull/173) est un excellent exemple des possibilités offertes par crossgen2 et des changements en profondeur que nous voulions introduire pour .NET 6 mais qui seront plus probablement pour .NET 7. Les "[bulles de version](https://github.com/dotnet/runtime/blob/main/docs/design/features/crossgen2-compilation-structure-enhancements.md)" sont un autre bon exemple.
Crossgen2 permet la [compilation croisée](https://fr.wikipedia.org/wiki/Cha%C3%AEne_de_compilation#Cha%C3%AEne_de_compilation_crois%C3%A9e) (d’où le nom "crossgen") à travers les dimensions du système d’exploitation et de l’architecture. Cela signifie que vous serez en mesure d’utiliser une seule machine de compilation pour générer du code natif pour toutes les cibles, du moins en ce qui concerne le code prêt à être exécuté. L’exécution et le test de ce code est une autre histoire, cependant, et vous aurez besoin du matériel et des systèmes d’exploitations appropriés pour cela.
La première étape consiste à compiler la plate-forme .NET elle-même avec crossgen2. Nous l’avons fait avec .NET 6, pour toutes les architectures. En conséquence, nous avons pu retirer l’ancien outil crossgen de cette version. Notez que crossgen2 ne s’applique qu’à CoreCLR et non aux applications basées sur [Mono](https://fr.wikipedia.org/wiki/Mono_(logiciel)) (qui ont un ensemble distinct d’outils de génération de code).
Ce projet – du moins au début – n’est pas orienté sur la performance. L’objectif est de permettre une bien meilleure architecture pour héberger le compilateur RyuJIT (ou tout autre compilateur) afin de générer du code d’une manière hors ligne (sans nécessiter ou démarrer le _runtime_).
Vous pourriez dire "hé… ne devez-vous pas lancer le _runtime_ pour exécuter crossgen2 s’il est écrit en C# ?". Oui, mais ce n’est pas ce que l’on entend par "hors ligne" dans ce contexte. Lorsque crossgen2 s’exécute, nous n’utilisons pas le [JIT](https://fr.wikipedia.org/wiki/Compilation_%C3%A0_la_vol%C3%A9e) fourni avec le _runtime_ sur lequel crossgen2 s’exécute pour générer du [code prêt à l’emploi (R2R)](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/readytorun-format.md). Cela ne fonctionnera pas, du moins pas avec les objectifs que nous avons. Imaginez que crossgen2 tourne sur une machine x64, et que nous devons générer du code pour Arm64. Crossgen2 charge le RyuJIT Arm64 – compilé pour x64 – comme un plugin natif, et l’utilise ensuite pour générer du code R2R Arm64. Les instructions machine ne sont qu’un flux d’octets qui sont enregistrés dans un fichier. Cela peut aussi fonctionner dans le sens inverse. Sur Arm64, crossgen2 peut générer du code x64 en utilisant le RyuJIT x64 compilé sur Arm64. Nous utilisons la même approche pour cibler du code x64 sur des machines x64. Crossgen2 charge un RyuJIT construit pour n’importe quelle configuration nécessaire. Cela peut sembler compliqué, mais c’est le genre de système qu’il faut mettre en place si l’on veut permettre un modèle de ciblage croisé sans faille, et c’est exactement ce que nous voulons.
Nous espérons utiliser le terme "crossgen2" pour une seule version, après quoi il remplacera le crossgen existant, et ensuite nous reviendrons à l’utilisation du terme "crossgen" pour "crossgen2".
Diagnostiques .NET : EventPipe
===========================
[EventPipe](https://docs.microsoft.com/en-us/dotnet/core/diagnostics/eventpipe) est notre mécanisme multiplateforme de sortie des événements, des données de performance et des compteurs, que ce soit en cours de traitement ou hors traitement. À partir de .NET 6, nous avons changé l’usage de C++ pour l’implémentation de l’outil par du C. Désormais et avec ce changement, Mono utilise également EventPipe. Cela signifie que [CoreCLR](https://github.com/dotnet/runtime) (le [_runtime_ commun](https://fr.wikipedia.org/wiki/Common_Language_Runtime)) et le _runtime_ [Mono](https://fr.wikipedia.org/wiki/Mono_(logiciel)) utilisent tous deux la même infrastructure événementielle, y compris les outils en ligne de commande [_.NET Diagnostics_](https://docs.microsoft.com/en-us/dotnet/core/diagnostics/).
Ce changement s’accompagne également d’une légère réduction de la taille de CoreCLR (11552 octets en moins pour libcoreclr.so)
Nous avons également apporté quelques [modifications pour améliorer le débit du EventPipe lorsqu’il est en cours d’utilisation](https://github.com/dotnet/runtime/issues/45518). Au cours des premières versions _preview_ de .NET 6, nous avons effectué une série de modifications qui ont permis d’améliorer le débit de 2,06 fois par rapport à celui de .NET 5 :
![eventPipe](https://user-images.githubusercontent.com/20667293/119393587-00cce680-bc86-11eb-87a0-2d6b9a575f84.png)
Plus haut est considéré comme meilleur pour ce banc d’essai. .NET 5 est la ligne bleue, et .NET 6 la ligne orange.
Kit de développement logiciel
===
Les changements suivants ont été apportés au kit de développement logiciel .NET :
Installations des charges de travail via la ligne de commande
--------------------------------------------
.NET 6 apporte le concept de [charges de travail](https://github.com/dotnet/designs/blob/main/accepted/2020/workloads/workloads.md) au sein du kit de développement. Les charges de travail sont des composants facultatifs qui peuvent être installés au-dessus du kit de développement .NET pour permettre divers cas d’usage. Les nouvelles charges de travail de .NET 6 sont : .NET MAUI et les charges de travail AOT de Blazor WebAssembly. Nous allons probablement créer de nouvelles charges de travail (éventuellement à partir du SDK existant) dans .NET 7. Le plus grand avantage des charges de travail est la réduction de la taille et l’aspect modulaire. Nous voulons réduire la taille du kit de développement au fil du temps et permettre d’installer uniquement les composants dont vous avez besoin. Ce modèle sera bon pour les machines des développeurs et encore meilleur pour l’intégration continue.
Les utilisateurs de Visual Studio n’ont pas vraiment à s’inquiéter des charges de travail. La fonctionnalité des charges de travail a été conçue pour qu’un orchestrateur d’installation comme Visual Studio puisse installer des charges de travail pour vous. Les charges de travail peuvent être gérées directement via la ligne de commande.
La fonctionnalité des charges de travail expose plusieurs verbes pour gérer les charges de travail, y compris les suivants :
- dotnet workload restore – installe les charges de travail requises par un projet donné ;
- dotnet workload install – installe une charge de travail nommée ;
- dotnet workload list – liste les charges de travail que vous avez installées ;
- dotnet workload update – met à jour toutes les charges de travail installées avec la dernière version disponible.
Le verbe update interroge nuget.org pour obtenir les manifestes de charges de travail mis à jour, met à jour les manifestes locaux, télécharge les nouvelles versions des charges de travail installées, puis supprime toutes les anciennes versions d’une charge de travail. Ceci est analogue à `apt update && apt upgrade -y` (utilisés sur les distributions Linux basées sur Debian). Il est censé de considérer les charges de travail comme un gestionnaire de paquets privé pour le kit de développement. Il est privé dans le sens où il n’est disponible que pour les composants du kit de développement. Nous pourrions reconsidérer cela à l’avenir.
Les commandes dotnet workloads fonctionnent dans le contexte du kit de développement local. Imaginez que vous ayez installé à la fois .NET 6 et .NET 7. Les commandes workloads fourniront des résultats différents pour chaque kit de développement puisque les charges de travail seront différentes (au moins différentes versions des mêmes charges de travail).
Notez que `dotnet workload install` copie les charges de travail de NuGet.org dans votre installation kit de développement. Il faudra donc l’exécuter avec des droits privilégiés ou utiliser sudo si l’emplacement de l’installation est protégé (c’est-à-dire à un emplacement admin/root).
Vérification de la version intégrée
-----------------------------
Pour savoir plus rapidement quels kits de développement et _runtimes_ sont disponibles, nous avons ajouté une nouvelle commande au kit de développement .NET 6 :
```sh
dotnet sdk check
```
Il vous indique si une version plus récente est disponible pour les kits de développement, les moteurs d’exécution ou les charges de travail .NET que vous avez installés. Vous pouvez voir la nouvelle expérience dans l’image suivante.
![sdk check](https://user-images.githubusercontent.com/12663534/119046999-374aee80-b972-11eb-8967-2111b7e7a586.png)
dotnet new
----------
Vous pouvez désormais rechercher de nouveaux modèles sur NuGet.org avec dotnet new --search.
Parmi les autres améliorations apportées à l’installation des modèles, citons la prise en charge de l’option `--interactive` pour la prise en charge des informations d’autorisation pour les flux NuGet privés.
Une fois les modèles de ligne de commande installés, vous pouvez vérifier si des mises à jour sont disponibles via `--update-check` et `--update-apply`.
Validation de paquet NuGet
------------------------
[Les outils de validation des paquets](https://docs.microsoft.com/dotnet/fundamentals/package-validation/overview) permettent aux développeurs de bibliothèques NuGet de valider que leurs paquets sont cohérents et bien formés.
Cela comprend :
- La vérification qu’il n’y a pas de changements incompatibles entre les versions ;
- Vérifie que le paquet a le même ensemble d’interfaces de programmation pour toutes les implémentations spécifiques à un runtime (comme par un exemple un paquet ciblant à la fois .NET Core 3.1 et .NET 6) ;
- Déterminer les éventuelles incompatibilités d’usage entre les différents cadriciels et _runtimes_.
Cet outil fait partie du kit de développement logiciel. La façon la plus simple de l’utiliser est de définir une nouvelle propriété dans votre fichier de projet :
```xml
true
```
Davantage d’analyseurs de code
---------------------
Dans .NET 5, nous avons livré environ 250 analyseurs avec le SDK .NET. Beaucoup d’entre eux existaient déjà, mais étaient livrés en dehors du SDK sous forme de paquets NuGet. Nous avons ajouté d’autres analyseurs pour .NET 6.
Pour rappel, [un analyseur de code](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix) a pour but de produire des suggestions sur le code en cours de développement. Lors de la compilation, le compilateur [Roslyn](https://en.wikipedia.org/wiki/Roslyn_(compiler)) fait appel aux analyseurs.
Par défaut, la plupart des nouveaux analyseurs sont activés au niveau **Info**. Vous pouvez activer ces analyseurs au niveau **Warning** [en configurant le mode d’analyse](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/overview#enable-additional-rules) comme suit :
```xml
All
```
Nous avons publié l’ensemble des analyseurs que nous voulions pour .NET 6 (plus quelques extras) et avons ensuite mis la plupart d’entre eux [à disposition pour implémentation](https://github.com/dotnet/runtime/issues?q=label%3Aup-for-grabs+label%3Acode-fixer+label%3Acode-analyzer). La communauté a ajouté plusieurs analyseurs, dont ceux ci-dessous :
Contributeurr Identifiant Titre
Newell Clark dotnet/runtime #33777 Utiliser la variante de string.Concat reposant sur Span
Newell Clark dotnet/runtime #33784 Préférez string.AsSpan() à string.SubString() dans vos analyses de chaînes
Newell Clark dotnet/runtime #33789 Redéfinissez Stream.ReadAsync/WriteAsync
Newell Clark dotnet/runtime #35343 Remplacez Dictionary<,>.Keys.Contains par ContainsKey
Newell Clark dotnet/runtime #45552 Utilisez String.Equals au lieu de String.Compare
Meik Tranel dotnet/runtime #47180 Utilisez String.Contains(char) au lieu de String.Contains(String)
_Merci à [Meik Tranel](https://github.com/MeikTranel) et à [Newell Clark](https://github.com/NewellClark)._
Utiliser des protections supplémentaires pour un code multiplateforme
--------------------------------------------------------
[L’analyseur de compatibilité de plate-forme](https://docs.microsoft.com/dotnet/standard/analyzers/platform-compat-analyzer) (règle [CA1416](https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1416)) reconnaît déjà les protections de plate-forme à l’aide des méthodes inOperatingSystem et RuntimeInformation, telles que OperatingSystem.IsWindows et OperatingSystem.IsWindowsVersionAtLeast. Cependant, [l’analyseur ne reconnaît pas d’autres possibilités de protection contre du code non-multiplateforme](https://github.com/dotnet/runtime/issues/44922) comme le résultat de la vérification de la plate-forme mis en cache dans un champ ou une propriété, ou une logique complexe de vérification de la plate-forme définie dans une méthode d’aide.
Pour permettre [d’étendre les protections existantes](https://github.com/dotnet/runtime/issues/51541), [nous avons ajouté de nouveaux attributs](https://github.com/dotnet/roslyn-analyzers/pull/5087) SupportedOSPlatformGuard et UnsupportedOSPlatformGuard pour annoter les membres d’une classe participant à la protection avec le nom et/ou la version de la plate-forme correspondante. Cette annotation est reconnue et respectée par l’analyseur de compatibilité de plate-forme.
### Utilisation
```csharp
// L'attribut spécifiant une plateforme non prise en charge.
[UnsupportedOSPlatformGuard("browser")]
#if TARGET_BROWSER
internal bool IsSupported => false;
#else
internal bool IsSupported => true;
#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
{
// Avertissement: Ce site d'appel est atteignable sur toutes les plateforms
// 'ApiNotSupportedOnBrowser()' est non pris en charge sur la plateforme : 'browser'
ApiNotSupportedOnBrowser();
if (IsSupported)
{
// Pas d'avertissement
ApiNotSupportedOnBrowser();
}
}
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
{
// Avertissement:
// Ce site d'appel est atteignable sur toutes les plateformes
// 'ApiOnlyWorkOnWindowsLinux()' est pris en charge seulement sur : 'Linux', 'Windows'.
ApiOnlyWorkOnWindowsLinux();
if (_isWindowOrLinux)
{
// Pas d'avertissement
ApiOnlyWorkOnWindowsLinux();
}
}
```
Le mot de la fin (ouf !)
========================
Il s’agit d’une nouvelle version importante de .NET, avec des améliorations presque équivalentes en termes de performances, de fonctionnalités, de convivialité et de sécurité. Nous espérons que vous trouverez de nombreuses améliorations qui vous rendront plus efficace et plus compétent dans votre développement quotidien et qui augmenteront les performances ou réduiront les coûts de vos applications en production. Nous avons déjà commencé à recevoir de bons retours de la part de ceux d’entre vous qui ont déjà commencé à utiliser .NET 6.
Chez [Microsoft](https://fr.wikipedia.org/wiki/Microsoft), nous sommes également dans les premières phases du déploiement de .NET 6, avec quelques applications clés déjà en production et beaucoup d’autres à venir dans les semaines et mois à venir.
.NET 6 est notre dernière version LTS à ce jour. Nous encourageons tout le monde à passer à cette version, en particulier si vous utilisez .NET 5. Nous pensons qu’il s’agit de la version de .NET la plus rapidement adoptée.
Cette version est le résultat du travail d’au moins 1000 personnes (mais probablement beaucoup plus). Il s’agit notamment de l’équipe .NET de Microsoft et de nombreux autres membres de la communauté. J’ai essayé d’inclure dans ce billet de nombreuses fonctionnalités apportées par la communauté. Merci à la communauté d’avoir pris le temps de les créer et de suivre notre processus de travail. J’espère que l’expérience a été gratifiante et qu’encore plus de personnes contribueront.
Ce billet est le fruit de la [collaboration de nombreuses personnes talentueuses](https://twitter.com/dsymetweets/status/1457494213994684416). Les contributions comprennent [la liste des fonctionnalités](https://github.com/dotnet/core/issues/6570) que l’équipe maintient tout au long de la conception de chaque version, ainsi que beaucoup de contenu important créé pour ce présent billet, et une tonne de corrections techniques et de prose qui sont nécessaires pour arriver à une qualité finale satisfaisante. Ce fut un plaisir de rédiger ce billet et tous les précédents pour vous.
Merci à vous d’être un développeur .NET.
Remerciements
========================
Merci à [Richard Lander](https://devblogs.microsoft.com/dotnet/author/rlander/), l’auteur originel de [la dépêche sur le blog officiel](https://devblogs.microsoft.com/dotnet/announcing-net-6/), d’avoir [donné son accord pour la création de cette traduction](https://devblogs.microsoft.com/dotnet/announcing-net-6/comment-page-4/#comment-14418).
Elle a été améliorée par davantage de liens et d’explications.