Nouveautés de .NET Core 3.0

Cet article décrit les nouveautés de .NET Core 3.0. Une des principales améliorations est la prise en charge des applications de bureau Windows (Windows uniquement). En utilisant le composant du SDK .NET Core 3.0 Windows Desktop, vous pouvez porter vos applications Windows Forms et Windows Presentation Foundation (WPF). Pour être clair, le composant Windows Desktop est pris en charge et inclus seulement sur Windows. Pour plus d’informations, consultez la section Bureau Windows plus loin dans cet article.

.NET Core 3.0 prend en charge C# 8.0. Il est vivement recommandé d’utiliser Visual Studio 2019 version 16.3 ou version ultérieure, Visual Studio pour Mac 8.3 ou version ultérieure ou Visual Studio Code avec la dernière extension C#.

Téléchargez et commencez à utiliser .NET Core 3.0 Preview 8 dès maintenant sur Windows, macOS ou Linux.

Pour plus d’informations sur la version, consultez l’annonce .NET Core 3.0.

.NET Core 3.0 RC 1 était considéré comme prêt pour la production par Microsoft et entièrement pris en charge. Si vous utilisez une version préliminaire, vous devez passer à la version RTM pour une prise en charge continue.

Améliorations du langage C# 8.0

C# 8.0 fait également partie de cette version, qui inclut la fonctionnalité de types de référence Nullable, les flux asynchrones et d’autres modèles. Pour plus d’informations sur les fonctionnalités de C# 8.0, consultez Nouveautés de C# 8.0.

Didacticiels relatifs aux fonctionnalités du langage C# 8.0 :

Des améliorations de langage ont été ajoutées pour prendre en charge les fonctionnalités d’API suivantes détaillées ci-dessous :

.NET Standard 2.1

.NET Core 3.0 implémente également .NET Standard 2.1. Toutefois, le modèle par défaut dotnet new classlib génère un projet qui cible toujours .NET Standard 2.0. Pour cibler .NET Standard 2.1, modifiez votre fichier projet et définissez la propriété TargetFramework sur netstandard2.1 :

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
  </PropertyGroup>

</Project>

Si vous utilisez Visual Studio, vous avez besoin de Visual Studio 2019, car Visual Studio 2017 ne prend pas en charge .NET Standard 2.1 ou .NET Core 3.0.

Compiler/déployer

Exécutables par défaut

.NET Core génère désormais des exécutables dépendant du framework par défaut. Ce comportement est nouveau pour les applications qui utilisent une version .NET Core installée de façon globale. Auparavant, seuls les déploiements autonomes produisaient un exécutable.

Lors de l’étape dotnet build ou dotnet publish, un exécutable (également appelé appHost) est créé, qui correspond à l’environnement et à la plateforme du kit de développement logiciel (SDK) que vous utilisez. Vous pouvez obtenir le même résultat avec ces exécutables, comme vous le feriez avec d’autres exécutables natifs comme :

  • Vous pouvez double-cliquer sur l’exécutable.
  • Vous pouvez lancer l’application directement à partir d’une invite de commandes, par exemple myapp.exe sous Windows, et ./myapp sous Linux et macOS.

macOS appHost et notarisation

macOS uniquement

À compter du kit SDK .NET Core 3.0 pour macOS notarisé, le paramètre permettant de produire un exécutable par défaut (appelé appHost) est désactivé par défaut. Pour plus d’informations, consultez Notarisation macOS Catalina et l’impact sur les téléchargements et les projets .NET Core.

Lorsque le paramètre appHost est activé, .NET Core génère un exécutable Mach-O natif lorsque vous créez ou publiez. Votre application s’exécute dans le contexte d’appHost lorsqu’elle est exécutée à partir du code source avec la commande dotnet run ou en démarrant directement l’exécutable Mach-O.

Sans appHost, la seule façon pour un utilisateur de démarrer une application dépendante de l’infrastructure consiste à utiliser la commande dotnet <filename.dll>. Un appHost est toujours créé lorsque vous publiez votre application de manière autonome.

Vous pouvez configurer l’appHost au niveau du projet ou basculer l’appHost pour une commande spécifique dotnet avec le paramètre -p:UseAppHost :

  • Fichier projet

    <PropertyGroup>
      <UseAppHost>true</UseAppHost>
    </PropertyGroup>
    
  • Paramètre de ligne de commande

    dotnet run -p:UseAppHost=true
    

Pour plus d’informations sur le paramètre UseAppHost, consultez Propriétés MSBuild pour Microsoft.NET.Sdk.

Exécutable monofichier

La commande dotnet publish prend en charge l’empaquetage de votre application dans un exécutable monofichier spécifique de la plateforme. L’exécutable est auto-extractible et contient toutes les dépendances (y compris natives) nécessaires à l’exécution de votre application. Lors de la première exécution de l’application, celle-ci est extraite d’un répertoire basé sur le nom de l’application et l’identificateur de la build. Le démarrage est plus rapide quand l’application est réexécutée. L’application n’a pas besoin de s’extraire elle-même une deuxième fois, sauf si une nouvelle version a été utilisée.

Pour publier un exécutable monofichier, définissez PublishSingleFile dans votre projet ou sur la ligne de commande avec la commande dotnet publish :

<PropertyGroup>
  <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
  <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

-ou-

dotnet publish -r win10-x64 -p:PublishSingleFile=true

Pour plus d’informations sur la publication monofichier, consultez le document conceptuel sur l’outil de regroupement monofichier.

Découpage d’assembly

Le SDK .NET Core 3.0 est fourni avec un outil qui peut réduire la taille des applications en analysant le langage intermédiaire et en supprimant les assemblys inutilisés.

Les applications autonomes incluent tous les éléments nécessaires pour exécuter votre code, sans nécessiter que .NET soit installé sur la machine hôte. Toutefois, il arrive souvent que l’application nécessite seulement un petit sous-ensemble de l’infrastructure pour fonctionner, et que les autres bibliothèques inutilisées puissent être supprimées.

.NET Core inclut désormais un paramètre qui utilisera l’outil de découpage de langage intermédiaire pour analyser le langage intermédiaire de votre application. Cet outil détecte ce que le code nécessite et supprime les bibliothèques inutilisées. Cet outil peut réduire considérablement la taille de déploiement de certaines applications.

Pour activer cet outil, ajoutez le paramètre <PublishTrimmed> dans votre projet et publiez une application autonome :

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
dotnet publish -r <rid> -c Release

Par exemple, le nouveau modèle de projet de console de base « hello world » inclus, lors de sa publication, atteint la taille d’environ 70 Mo. Avec <PublishTrimmed>, sa taille est réduite à environ 30 Mo.

Il est important de prendre en compte le fait que les applications ou infrastructures (dont ASP.NET Core et WPF) qui utilisent la réflexion ou des fonctionnalités dynamiques associées cesseront souvent de fonctionner après cette troncature. Cette rupture se produit car l’outil de découpage ne connaît pas ce comportement dynamique et ne peut pas déterminer les types d’infrastructure nécessaires pour la réflexion. L’outil de découpage de langage intermédiaire peut être configuré pour être conscient de ce scénario.

Avant toute chose, veillez à tester votre application après réduction.

Pour plus d’informations sur l’outil de découpage de langage intermédiaire, consultez la documentation ou visitez le référentiel mono/éditeur de liens.

Compilation hiérarchisée

La compilation hiérarchisée est activée par défaut avec .NET Core 3.0. Cette fonctionnalité permet au runtime d’utiliser de manière plus adaptative le compilateur juste-à-temps (JIT) pour obtenir de meilleures performances.

Le principal avantage de la compilation hiérarchisée est de fournir deux méthodes de jitting : dans un niveau de qualité inférieure mais plus rapide ou un niveau de qualité supérieure mais plus lent. La qualité fait référence à la façon dont la méthode est optimisée. TC permet d’améliorer les performances d’une application au fur et à mesure qu’elle passe par différentes étapes d’exécution, du démarrage à l’état stable. Lorsque la compilation hiérarchisée est désactivée, chaque méthode est compilée d’une manière unique qui est axée sur les performances à l’état stable par rapport aux performances de démarrage.

Lorsque TC est activé, le comportement suivant s’applique à la compilation de méthode lorsqu’une application démarre :

  • Si la méthode comporte du code compilé à l’avance ou ReadyToRun, le code prégénéré est utilisé.
  • Sinon, la méthode est traitée avec Jit. En règle générale, ces méthodes sont des génériques sur les types valeur.
    • Le JIT rapide produit plus rapidement du code de qualité inférieure (ou moins optimisé). Dans .NET Core 3.0, le JIT rapide est activé par défaut pour les méthodes qui ne contiennent pas de boucles et est préféré au démarrage.
    • L’optimisation complète du JIT produit du code de qualité supérieure (ou plus optimisé) plus lentement. Pour les méthodes où le JIT rapide n’est pas utilisé (par exemple, si la méthode est attribuée avec MethodImplOptions.AggressiveOptimization), le JIT entièrement optimisé est utilisé.

Pour les méthodes fréquemment appelées, le compilateur juste-à-temps crée finalement du code entièrement optimisé en arrière-plan. Le code optimisé remplace ensuite le code précompilé pour cette méthode.

Le code généré par le JIT rapide peut s’exécuter plus lentement, allouer plus de mémoire ou utiliser plus d’espace de pile. En cas de problème, vous pouvez désactiver le JIT rapide à l’aide de cette propriété MSBuild dans le fichier projet :

<PropertyGroup>
  <TieredCompilationQuickJit>false</TieredCompilationQuickJit>
</PropertyGroup>

Pour désactiver complètement TC, utilisez cette propriété MSBuild dans votre fichier projet :

<PropertyGroup>
  <TieredCompilation>false</TieredCompilation>
</PropertyGroup>

Conseil

Si vous modifiez ces paramètres dans le fichier projet, vous devrez peut-être effectuer une build propre pour que les nouveaux paramètres soient reflétés (supprimez les répertoires obj et bin et régénérez).

Pour plus d’informations sur la configuration de la compilation au moment de l’exécution, consultez Options de configuration d’exécution pour la compilation.

Images ReadyToRun

Vous pouvez améliorer le temps de démarrage de votre application .NET Core en compilant les assemblys de votre application au format ReadyToRun (R2R). R2R est une forme de compilation ahead-of-time (AOT).

Les fichiers binaires R2R améliorent les performances de démarrage en réduisant la quantité de travail que le compilateur juste-à-temps (JIT) doit faire lorsque votre application est chargée. Les fichiers binaires contiennent du code natif similaire à ce que la compilation JIT produirait. Cependant, les fichiers binaires R2R sont plus grands, car ils contiennent à la fois le code du langage intermédiaire (IL), qui est toujours nécessaire pour certains scénarios, et la version native du même code. R2R est disponible seulement quand vous publiez une application autonome qui cible des environnements d’exécution spécifiques (RID), comme Linux x64 ou Windows x64.

Pour compiler votre projet en ReadyToRun, procédez comme suit :

  1. Ajoutez le paramètre <PublishReadyToRun> à votre projet :

    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
  2. Publiez une application autonome. Par exemple, cette commande crée une application autonome pour la version 64 bits de Windows :

    dotnet publish -c Release -r win-x64 --self-contained
    

Restrictions d’architecture/de multiplateforme

Le compilateur ReadyToRun ne prend actuellement pas en charge le ciblage croisé. Vous devez compiler sur une cible donnée. Par exemple, si vous souhaitez avoir des images R2R Windows x64, vous devez exécuter la commande de publication sur cet environnement.

Exceptions au ciblage croisé :

  • Windows x64 peut être utilisé pour compiler des images Windows ARM32, ARM64 et x86.
  • Windows x86 peut être utilisé pour compiler des images Windows ARM32.
  • Linux x64 peut être utilisé pour compiler des images Linux ARM32 et ARM64.

Pour plus d’informations, consultez Prêt à s’exécuter.

Runtime/SDK

Restauration par progression du runtime de version majeure

.NET Core 3.0 introduit une fonctionnalité que vous pouvez choisir d’utiliser et qui permet de restaurer par progression votre application vers la dernière version majeure de .NET Core. En outre, un nouveau paramètre a été ajouté pour contrôler la façon dont la restauration par progression est appliquée à votre application. Ce paramètre peut être configuré des façons suivantes :

  • Propriété du fichier projet : RollForward
  • Propriété du fichier config du runtime : rollForward
  • Variable d’environnement : DOTNET_ROLL_FORWARD
  • Argument de ligne de commande : --roll-forward

L’une des valeurs suivantes doit être spécifiée. Si le paramètre est omis, Minor est la valeur par défaut.

  • LatestPatch
    Restauration par progression vers la version de correctif la plus élevée. Cette valeur désactive la restauration par progression d’une version mineure.
  • Secondaire
    Restauration par progression vers la version mineure supérieure la plus basse, si la version mineure demandée est manquante. Si la version mineure demandée est présente, la stratégie LatestPatch est utilisée.
  • Majeure
    Restauration par progression vers la version majeure supérieure la plus basse, et la version mineure la plus basse, si la version majeure demandée est manquante. Si la version majeure demandée est présente, la stratégie Minor est utilisée.
  • LatestMinor
    Restauration par progression vers la version mineure la plus élevée, si la version mineure demandée est présente. Conçu pour les scénarios d’hébergement de composant.
  • LatestMajor
    Restauration par progression vers la version majeure la plus élevée et la version mineure la plus élevée, si la version majeure demandée est présente. Conçu pour les scénarios d’hébergement de composant.
  • Désactiver
    Ne pas effectuer de restauration par progression. Lier uniquement à la version spécifiée. Cette stratégie n’est pas recommandée pour une utilisation générale, car elle désactive la possibilité d’effectuer une restauration par progression vers les derniers correctifs. Cette valeur est recommandée uniquement à des fins de test.

Outre le paramètre Disable, tous les paramètres utilisent la version de correctif disponible la plus élevée.

Par défaut, si la version demandée (comme spécifié dans .runtimeconfig.json pour l’application) est une version commerciale, seules les versions commerciale sont prises en compte pour la restauration par progression. Toutes les versions en préversion sont ignorées. S’il n’existe aucune version commerciale correspondante, les préversions sont prises en compte. Ce comportement peut être modifié en définissant DOTNET_ROLL_FORWARD_TO_PRERELEASE=1, auquel cas toutes les versions sont toujours prises en compte.

Dépendances de copies de build

La commande dotnet build copie maintenant les dépendances NuGet pour votre application à partir du cache NuGet vers le dossier de sortie de build. Auparavant, les dépendances étaient copiées uniquement dans le cadre de dotnet publish.

Il existe certaines opérations, telles que le découpage et la publication de pages de type Razor, qui nécessitent toujours la publication.

Outils locaux

.NET Core 3.0 introduit des outils locaux. Les outils locaux sont similaires aux outils globaux, mais ils sont associés à un emplacement particulier sur le disque. Les outils locaux ne sont pas disponibles globalement et sont distribués en tant que packages NuGet.

Les outils locaux s’appuient sur un nom de fichier manifeste dotnet-tools.json dans votre répertoire actuel. Ce fichier manifeste définit les outils qui doivent être disponibles dans ce dossier et sous-celui-ci. Vous pouvez distribuer le fichier manifeste avec votre code pour que toute personne qui utilise votre code puisse restaurer et utiliser les mêmes outils.

Pour les outils locaux et globaux, une version compatible du runtime est requise. De nombreux outils actuellement sur NuGet.org ciblent le runtime .NET Core 2.1. Pour installer ces outils de façon locale ou globale, vous devez toujours installer le runtime NET Core 2.1.

Nouvelles options global.json

Le fichier global.json comporte de nouvelles options qui offrent plus de flexibilité lorsque vous essayez de définir la version du kit SDK .NET Core utilisée. Les nouvelles options sont les suivantes :

  • allowPrerelease : indique si le programme de résolution du kit de développement logiciel (SDK) doit prendre en compte les préversions lors de la sélection de la version du kit de développement logiciel (SDK) à utiliser.
  • rollForward : indique la stratégie de restauration par progression à utiliser lors de la sélection d’une version du SDK, soit comme secours lorsqu’une version spécifique du SDK est manquante, soit en tant que directive pour utiliser une version ultérieure.

Pour plus d’informations sur les modifications, notamment les valeurs par défaut, les valeurs prises en charge et les nouvelles règles de correspondance, consultez la présentation global.json.

Tailles de tas de garbage collection plus petites

La taille de tas par défaut du récupérateur de mémoire a été réduite, aboutissant à une diminution de la quantité de mémoire utilisée par .NET Core. Ce changement est plus conforme au budget d’allocation de génération 0 avec les tailles des caches des processeurs modernes.

Prise en charge de grandes pages du garbage collection

Les grandes pages (également appelées HugePages sur Linux) sont une fonctionnalité qui permet au système d’exploitation d’établir des régions de mémoire plus grandes que la taille de page native (souvent 4 Ko) pour améliorer les performances de l’application qui demande ces grandes pages.

Vous pouvez maintenant configurer le récupérateur de mémoire avec la définition GCLargePages en tant que fonctionnalité que vous pouvez choisir d’utiliser et qui permet d’allouer de grandes pages sur Windows.

Windows Desktop et COM

Windows Installer pour le kit SDK .NET Core

Le programme d’installation MSI pour Windows a changé à compter de .NET Core 3.0. Les programmes d’installation du SDK mettent désormais à niveau les versions des plages de fonctionnalités du SDK. Les plages de fonctionnalités sont définies dans les groupes hundreds de la section patch du numéro de version. Par exemple, 3.0.101 et 3.0.201 sont des versions dans deux plages de fonctionnalités différentes, tandis que 3.0.101 et 3.0.199 se trouvent dans la même plages de fonctionnalités. En outre, quand le SDK .NET Core 3.0.101 est installé, le SDK .NET Core 3.0.100 est supprimé de la machine s’il existe. Quand le SDK .NET Core 3.0.200 est installé sur la même machine, le SDK .NET Core 3.0.101 n’est pas supprimé.

Pour plus d’informations sur la gestion des versions, consultez Vue d’ensemble de la gestion des versions .NET Core.

Ordinateurs Windows

.NET Core 3.0 prend en charge les applications de bureau Windows utilisant Windows Presentation Foundation (WPF) et Windows Forms. Ces infrastructures prennent également en charge l’utilisation de contrôles modernes et le style Fluent à partir de la bibliothèque XAML de l’interface utilisateur Windows (WinUI) via des îles XAML.

Le composant Bureau Windows fait partie du SDK .NET Core 3.0 Windows.

Vous pouvez créer une nouvelle application WPF ou Windows Forms à l’aide des commandes dotnet suivantes :

dotnet new wpf
dotnet new winforms

Visual Studio 2019 ajoute des modèles Nouveau projet pour Windows Forms et WPF .NET Core 3.0.

Pour plus d’informations sur la façon de porter une application .NET Framework existante, consultez Porter des projets WPF et Porter des projets Windows Forms.

Haute résolution WinForms

Les applications Windows Forms .NET Core peuvent définir le mode de haute résolution avec Application.SetHighDpiMode(HighDpiMode). La méthode SetHighDpiMode définit le mode de haute résolution correspondant, sauf si le paramètre a été défini par d’autres moyens, comme App.Manifest ou P/Invoke avant Application.Run.

Les valeurs highDpiMode possibles, telles qu’exprimées par l’enum System.Windows.Forms.HighDpiMode, sont les suivantes :

  • DpiUnaware
  • SystemAware
  • PerMonitor
  • PerMonitorV2
  • DpiUnawareGdiScaled

Pour plus d’informations sur les modes de haute résolution, consultez High DPI Desktop Application Development on Windows (Développement d’applications de bureau haute résolution sur Windows).

Création de composants COM

Sur Windows, vous pouvez maintenant créer des composants gérés appelables par COM. Cette fonctionnalité est essentielle pour utiliser .NET Core avec les modèles de compléments COM et également pour assurer la parité avec .NET Framework.

Contrairement à .NET Framework, où mscoree.dll était utilisé comme serveur COM, .NET Core ajoute une dll de lanceur natif au répertoire bin quand vous générez votre composant COM.

Pour obtenir un exemple montrant comment créer un composant COM et le consommer, consultez la démonstration COM.

Interopérabilité native Windows

Windows offre une API native riche sous la forme d’API C plates, de COM et de WinRT. Tandis que .NET Core prend en charge P/Invoke, .NET Core 3.0 ajoute la possibilité de cocréer des API COM et d’activer des API WinRT. Pour obtenir un exemple de code, consultez la démonstration Excel.

Déploiement de MSIX

MSIX est un nouveau format de package d’application Windows. Il peut être utilisé pour déployer des applications de poste de travail .NET Core 3.0 pour Windows 10.

Le projet de package d’application Windows, disponible dans Visual Studio 2019, vous permet de créer des packages MSIX avec des applications .NET Core autonomes.

Le fichier projet .NET Core doit spécifier les runtimes pris en charge dans la propriété <RuntimeIdentifiers> :

<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>

Améliorations apportées à Linux

SerialPort pour Linux

.NET Core 3.0 offre une prise en charge de base de System.IO.Ports.SerialPort sur Linux.

Auparavant, .NET Core était uniquement pris en charge au moyen de SerialPort sur Windows.

Pour plus d’informations sur la prise en charge limitée du port série sur Linux, consultez GitHub issue #33146.

Docker et limites de mémoire cgroup

L’exécution de .NET Core 3.0 sur Linux avec Docker fonctionne mieux avec les limites de mémoire cgroup. L’exécution d’un conteneur Docker avec des limites de mémoire, par exemple avec docker run -m, change le comportement de .NET Core.

  • Taille de tas par défaut du récupérateur de mémoire (GC) : au maximum 20 Mo ou 75 % de la limite de mémoire sur le conteneur.
  • Une taille explicite peut être définie sous forme de nombre absolu ou de pourcentage de la limite cgroup.
  • La taille de segment réservée minimale par tas GC est de 16 Mo. Cette taille réduit le nombre de segments de mémoire qui sont créés sur les machines.

Prise en charge de GPIO pour Raspberry Pi

Deux packages ont été publiés sur NuGet, que vous pouvez utiliser pour la programmation de GPIO :

Les packages GPIO incluent des API pour les appareils GPIO, SPI, I2C et PWM. Le package de liaisons IoT comprend des liaisons d’appareil. Pour plus d’informations, consultez le dépôt GitHub devices.

Prise en charge d’Arm64 Linux

.NET Core 3.0 ajoute la prise en charge d’ARM64 pour Linux. Actuellement, Arm64 est principalement utilisé dans des scénarios IoT. Pour plus d’informations, consultez .NET Core Arm64 Status.

Des images Docker pour .NET Core sur Arm64 sont disponibles pour Alpine, Debian et Ubuntu.

Notes

La prise en charge des systèmes d’exploitation macOS Arm64 (ou « Apple Silicon ») et Windows Arm64 a été ajoutée ultérieurement dans .NET 6.

Sécurité

TLS 1.3 et OpenSSL 1.1.1 sous Linux

.NET Core tire désormais parti de la prise en charge de TLS 1.3 dans OpenSSL 1.1.1, si disponible dans un environnement donné. Avec TLS 1.3 :

  • Les délais de connexion sont améliorés grâce à une réduction des allers-retours requis entre le client et le serveur.
  • La sécurité est améliorée en raison de la suppression de différents algorithmes de chiffrement obsolètes et non sécurisés.

.NET Core 3.0 utilise OpenSSL 1.1.1, OpenSSL 1.1.0 ou OpenSSL 1.0.2 sur un système Linux s’ils sont disponibles. Quand OpenSSL 1.1.1 est disponible, les types System.Net.Security.SslStream et System.Net.Http.HttpClient utilisent TLS 1.3 (sous réserve que le client et le serveur prennent en charge TLS 1.3).

Important

Windows et macOS ne prennent pas encore en charge TLS 1.3.

L’exemple C# 8.0 suivant montre comment .NET Core 3.0 sur Ubuntu 18.10 se connecte à https://www.cloudflare.com :

using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace whats_new
{
    public static class TLS
    {
        public static async Task ConnectCloudFlare()
        {
            var targetHost = "www.cloudflare.com";

            using TcpClient tcpClient = new TcpClient();

            await tcpClient.ConnectAsync(targetHost, 443);

            using SslStream sslStream = new SslStream(tcpClient.GetStream());

            await sslStream.AuthenticateAsClientAsync(targetHost);
            await Console.Out.WriteLineAsync($"Connected to {targetHost} with {sslStream.SslProtocol}");
        }
    }
}

Chiffrements

.NET Core 3.0 prend en charge les chiffrements AES-GCM et AES-CCM, implémentés avec System.Security.Cryptography.AesGcm et System.Security.Cryptography.AesCcm respectivement. Ces algorithmes sont tous deux des algorithmes AEAD (Authenticated Encryption with Association Data).

Le code suivant montre l’utilisation du chiffrement AesGcm pour chiffrer et déchiffrer des données aléatoires.

using System;
using System.Linq;
using System.Security.Cryptography;

namespace whats_new
{
    public static class Cipher
    {
        public static void Run()
        {
            // key should be: pre-known, derived, or transported via another channel, such as RSA encryption
            byte[] key = new byte[16];
            RandomNumberGenerator.Fill(key);

            byte[] nonce = new byte[12];
            RandomNumberGenerator.Fill(nonce);

            // normally this would be your data
            byte[] dataToEncrypt = new byte[1234];
            byte[] associatedData = new byte[333];
            RandomNumberGenerator.Fill(dataToEncrypt);
            RandomNumberGenerator.Fill(associatedData);

            // these will be filled during the encryption
            byte[] tag = new byte[16];
            byte[] ciphertext = new byte[dataToEncrypt.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Encrypt(nonce, dataToEncrypt, ciphertext, tag, associatedData);
            }

            // tag, nonce, ciphertext, associatedData should be sent to the other part

            byte[] decryptedData = new byte[ciphertext.Length];

            using (AesGcm aesGcm = new AesGcm(key))
            {
                aesGcm.Decrypt(nonce, ciphertext, tag, decryptedData, associatedData);
            }

            // do something with the data
            // this should always print that data is the same
            Console.WriteLine($"AES-GCM: Decrypted data is {(dataToEncrypt.SequenceEqual(decryptedData) ? "the same as" : "different than")} original data.");
        }
    }
}

Importation/exportation d’une clé de chiffrement

.NET Core 3.0 prend en charge l’importation et l’exportation de clés publiques et privées asymétriques aux formats standard. Vous n’avez pas besoin d’utiliser un certificat X.509.

Tous les types de clés, tels que RSA, DSA, ECDsa et ECDiffieHellman, prennent en charge les formats suivants :

  • Clé publique

    • X.509 SubjectPublicKeyInfo
  • Private key

    • PKCS#8 PrivateKeyInfo
    • PKCS#8 EncryptedPrivateKeyInfo

Les clés RSA prennent également en charge :

  • Clé publique

    • PKCS#1 RSAPublicKey
  • Private key

    • PKCS#1 RSAPrivateKey

Les méthodes d’exportation produisent des données binaires encodées au format DER, tout comme les méthodes d’importation. Si une clé est stockée au format PEM compatible avec le texte, l’appelant devra décoder le contenu au format base64 avant d’appeler une méthode d’importation.

using System;
using System.Security.Cryptography;

namespace whats_new
{
    public static class RSATest
    {
        public static void Run(string keyFile)
        {
            using var rsa = RSA.Create();

            byte[] keyBytes = System.IO.File.ReadAllBytes(keyFile);
            rsa.ImportRSAPrivateKey(keyBytes, out int bytesRead);

            Console.WriteLine($"Read {bytesRead} bytes, {keyBytes.Length - bytesRead} extra byte(s) in file.");
            RSAParameters rsaParameters = rsa.ExportParameters(true);
            Console.WriteLine(BitConverter.ToString(rsaParameters.D));
        }
    }
}

Les fichiers PKCS#8 peuvent être inspectés avec System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo, tandis que les fichiers PFX/PKCS#12 peuvent être inspectés avec System.Security.Cryptography.Pkcs.Pkcs12Info. Les fichiers PFX/PKCS#12 peuvent être manipulés avec System.Security.Cryptography.Pkcs.Pkcs12Builder.

Modifications de l’API .NET Core 3.0

Plages et index

Le nouveau type System.Index peut être utilisé pour l’indexation. Vous pouvez en créer un à partir d’un int qui compte à partir du début, ou avec un opérateur (C#) ^ préfixé qui compte à partir de la fin :

Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"

Il existe également le type System.Range, composé de deux valeurs Index, une pour le début et une pour la fin, et qui peut être écrit avec une expression de plage (C#) x..y. Vous pouvez indexer ensuite avec un Range, ce qui génère une tranche :

var slice = a[i1..i2]; // { 3, 4, 5 }

Pour plus d’informations, consultez le tutoriel sur les plages et les index.

Flux asynchrones

Le type IAsyncEnumerable<T> est une nouvelle version asynchrone de IEnumerable<T>. Le langage vous permet d’utiliser await foreach sur IAsyncEnumerable<T> pour consommer ses éléments, et yield return sur ceux-ci pour produire des éléments.

L’exemple suivant montre la production et la consommation de flux de données asynchrones. L’instruction foreach est asynchrone et utilise elle-même yield return afin de produire un flux asynchrone pour les appelants. Ce modèle (qui utilise yield return) est le modèle recommandé pour produire des flux de données asynchrones.

async IAsyncEnumerable<int> GetBigResultsAsync()
{
    await foreach (var result in GetResultsAsync())
    {
        if (result > 20) yield return result;
    }
}

Outre la possibilité d’effectuer une opération await foreach, vous pouvez également créer des itérateurs asynchrones, par exemple un itérateur qui retourne un objet IAsyncEnumerable/IAsyncEnumerator auquel vous pouvez à la fois appliquer des opérations await et yield. Pour les objets qui doivent être supprimés, vous pouvez utiliser IAsyncDisposable, qui implémentent différents types BCL, notamment Stream et Timer.

Pour plus d’informations, consultez le tutoriel sur les flux asynchrones.

Virgule flottante IEEE

Les API de virgule flottante sont en cours de mise à jour pour devenir conformes à la révision 754-2008 d’IEEE. L’objectif de ces modifications est d’exposer toutes les opérations requises et de s’assurer qu’elles sont conformes au comportement de la spécification IEEE. Pour plus d’informations sur les améliorations à virgule flottante, consultez le billet de blog Floating-Point Parsing and Formatting improvements in .NET Core 3.0.

Les correctifs de l’analyse et de la mise en forme comprennent :

  • Analyse et arrondi corrects des entrées, quelle que soit leur longueur.
  • Analyse et mise en forme correctes des zéros négatifs.
  • Analyse correcte de Infinity et NaN en effectuant une vérification sans tenir compte de la casse et en autorisant un signe + facultatif de début là où c’est applicable.

Les nouvelles API System.Math incluent :

  • BitIncrement(Double) et BitDecrement(Double)
    Correspond aux opérations IEEE nextUp et nextDown. Elles retournent le plus petit nombre à virgule flottante dont la valeur est supérieure ou inférieure à l’entrée (respectivement). Par exemple, Math.BitIncrement(0.0) retourne double.Epsilon.

  • MaxMagnitude(Double, Double) et MinMagnitude(Double, Double)
    Correspond aux opérations IEEE maxNumMag et minNumMag. Elles retournent la valeur la plus grande ou la plus petite des deux entrées (respectivement). Par exemple, Math.MaxMagnitude(2.0, -3.0) retourne -3.0.

  • ILogB(Double)
    Correspond à l’opération IEEE logB qui retourne une valeur intégrale ; elle retourne le logarithme de base 2 intégral du paramètre d’entrée. Cette méthode est identique à floor(log2(x)), mais effectuée avec une erreur d’arrondi minimale.

  • ScaleB(Double, Int32)
    Correspond à l’opération IEEE scaleB qui prend une valeur intégrale ; elle retourne x * pow(2, n), mais est effectuée avec une erreur d’arrondi minimale.

  • Log2(Double)
    Correspond à l’opération IEEE log2 ; elle retourne le logarithme de base 2. Son erreur d’arrondi est minimale.

  • FusedMultiplyAdd(Double, Double, Double)
    Correspond à l’opération IEEE fma ; elle effectue une multiplication-addition fusionnée. Elle effectue (x * y) + z comme une seule opération, avec une erreur d’arrondi minimale. Un exemple est FusedMultiplyAdd(1e308, 2.0, -1e308), qui retourne 1e308. L’opération régulière (1e308 * 2.0) - 1e308 retourne double.PositiveInfinity.

  • CopySign(Double, Double)
    Correspond à l’opération IEEE copySign ; elle retourne la valeur de x, mais avec le signe de y.

Intrinsèques dépendant de la plateforme .NET

Des API ont été ajoutées, qui permettent d’accéder à certaines instructions de l’UC orientées performances, comme les ensembles SIMD ou les ensembles d’instructions de manipulation de bits. Ces instructions peuvent améliorer les performances dans certains scénarios de matière significative, comme le traitement efficace de données en parallèle.

Le cas échéant, les bibliothèques .NET ont commencé à utiliser ces instructions pour améliorer les performances.

Pour plus d’informations, consultez Intrinsèques dépendant de la plateforme .NET.

API de version de .NET Core améliorées

À compter de .NET Core 3.0, les API de version fournies avec .NET Core retournent les informations souhaitées. Par exemple :

System.Console.WriteLine($"Environment.Version: {System.Environment.Version}");

// Old result
//   Environment.Version: 4.0.30319.42000
//
// New result
//   Environment.Version: 3.0.0
System.Console.WriteLine($"RuntimeInformation.FrameworkDescription: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}");

// Old result
//   RuntimeInformation.FrameworkDescription: .NET Core 4.6.27415.71
//
// New result (notice the value includes any preview release information)
//   RuntimeInformation.FrameworkDescription: .NET Core 3.0.0-preview4-27615-11

Avertissement

Modification avec rupture. Il s’agit techniquement d’une modification avec rupture, car le schéma de gestion de version a changé.

Prise en charge JSON intégrée rapide

Les utilisateurs de .NET se sont largement appuyés sur Newtonsoft.Json et d’autres bibliothèques JSON populaires, qui restent de bons choix. Newtonsoft.Json utilise des chaînes .NET comme type de données de base, au format UTF-16.

La nouvelle prise en charge JSON intégrée offre de hautes performances, une faible allocation et fonctionne avec du texte JSON encodé en UTF-8. Pour plus d’informations sur l’espace de noms et les types System.Text.Json, consultez les articles suivants :

Assistance HTTP/2

Le type System.Net.Http.HttpClient prend en charge le protocole HTTP/2. Si HTTP/2 est activé, la version du protocole HTTP est négociée par le biais de TLS/ALPN, et HTTP/2 n’est utilisée que si le serveur le choisit.

Le protocole par défaut reste HTTP/1.1, mais HTTP/2 peut être activé de deux manières différentes. Tout d’abord, vous pouvez définir le message de requête HTTP de sorte à utiliser HTTP/2 :

var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };

// HTTP/1.1 request
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

// HTTP/2 request
using (var request = new HttpRequestMessage(HttpMethod.Get, "/") { Version = new Version(2, 0) })
using (var response = await client.SendAsync(request))
    Console.WriteLine(response.Content);

Ensuite, vous pouvez modifier HttpClient pour utiliser HTTP/2 par défaut :

var client = new HttpClient()
{
    BaseAddress = new Uri("https://localhost:5001"),
    DefaultRequestVersion = new Version(2, 0)
};

// HTTP/2 is default
using (var response = await client.GetAsync("/"))
    Console.WriteLine(response.Content);

Souvent, lorsque vous développez une application, vous souhaiterez utiliser une connexion non chiffrée. Si vous savez que le point de terminaison cible utilisera HTTP/2, vous pouvez activer les connexions non chiffrées pour HTTP/2. Vous pouvez activer cela en définissant la variable d’environnement DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT sur 1 ou en l’activant dans le contexte de l’application :

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

Étapes suivantes