web-dev-qa-db-fra.com

C # 8 prend-il en charge le .NET Framework?

Dans les paramètres de construction avancée de Visual Studio 2019, C # 8 ne semble pas être disponible pour un projet .NET Framework, uniquement (comme dans l'image ci-dessous) pour un projet .NET Core 3.0:

enter image description here

C # 8 prend-il en charge le .NET Framework?

96
James Harcourt

Oui, C # 8 peut être utilisé avec .NET Framework et d'autres cibles plus anciennes que .NET Core 3.0/.NET Standard 2.1 dans Visual Studio 2019 (ou les anciennes versions de Visual Studio si vous installez un package Nuget ).

La version linguistique doit être définie sur 8.0 dans le fichier csproj.

La plupart des fonctionnalités, mais pas toutes, sont disponibles quel que soit le cadre ciblé.


Des fonctionnalités qui fonctionnent

Les fonctionnalités suivantes sont uniquement des modifications de syntaxe; ils fonctionnent quel que soit le cadre:

Fonctionnalités pouvant fonctionner

Ceux-ci nécessitent de nouveaux types qui ne sont pas dans le .NET Framework. Ils ne peuvent être utilisés qu'en conjonction avec des packages Nuget "polyfill" ou des fichiers de code:

Membres de l'interface par défaut - ne fonctionnent pas

Membres de l'interface par défaut ne compilera pas sous .NET Framework et ne fonctionnera jamais car ils nécessitent des modifications d'exécution dans le CLR. Le .NET CLR est maintenant figé car .NET Core est désormais la voie à suivre.

Pour plus d'informations sur ce qui fonctionne et ne fonctionne pas, et sur les polyfills possibles, voir l'article de Stuart Lang, C # 8.0 et .NET Standard 2.0 - Faire des choses non prises en charge .


Code

Le projet C # suivant ciblant .NET Framework 4.8 et utilisant les types de référence nullable C # 8 se compile dans Visual Studio 16.2.0. Je l'ai créé en choisissant le modèle de bibliothèque de classes standard .NET, puis en le modifiant pour cibler .NET Framework à la place:

.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net48</TargetFrameworks>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

.cs:

namespace ClassLibrary1
{
    public class Class1
    {
        public string? NullableString { get; set; }
    }
}

J'ai ensuite essayé un projet WinForms .NET Framework 4.5.2, en utilisant un _ .csproj format et a ajouté la même propriété de type de référence nullable. J'ai changé le type de langue dans la boîte de dialogue des paramètres de Visual Studio Advanced Build (désactivé dans 16.3) en latest et j'ai enregistré le projet. Bien sûr, ce point ne se construit pas. J'ai ouvert le fichier de projet dans un éditeur de texte et changé latest en preview dans la configuration de construction PropertyGroup:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <LangVersion>preview</LangVersion>

J'ai ensuite activé la prise en charge des types de référence nullables en ajoutant <Nullable>enable</Nullable> vers le principal PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

J'ai rechargé le projet, et il se construit.


Les détails sanglants

Lorsque cette réponse a été écrite pour la première fois, C # 8 était en avant-première et beaucoup de travail de détective a été impliqué. Je laisse cette information ici pour la postérité. N'hésitez pas à le sauter si vous n'avez pas besoin de connaître tous les détails sanglants.

Historiquement, le langage C # a été principalement neutre vis-à-vis du framework - c'est-à-dire capable de compiler des versions plus anciennes du Framework - bien que certaines fonctionnalités aient nécessité de nouveaux types ou un support CLR.

La plupart des passionnés de C # auront lu l'entrée de blog Building C # 8. de Mads Torgersen, qui explique que certaines fonctionnalités de C # 8 ont des dépendances de plateforme:

Les flux, indexeurs et plages asynchrones reposent tous sur de nouveaux types de framework qui feront partie de .NET Standard 2.1 ... .NET Core 3.0 ainsi que Xamarin, Unity et Mono implémenteront tous .NET Standard 2.1, mais .NET Framework 4.8 le fera ne pas. Cela signifie que les types requis pour utiliser ces fonctionnalités ne seront pas disponibles sur .NET Framework 4.8.

Cela ressemble un peu à Value Tuples qui ont été introduits dans C # 7. Cette fonctionnalité nécessitait de nouveaux types - les structures ValueTuple - qui n'étaient pas disponibles dans les versions de NET Framework inférieures à 4.7 ou .NET Standard plus vieux que 2.0. Cependant , C # 7 peut toujours être utilisé dans les anciennes versions de .NET, soit sans tuples de valeur, soit avec eux en installant le System.ValueTuple Paquet Nuget . Visual Studio l'a compris et tout allait bien avec le monde.

Cependant, Mads a également écrit:

Pour cette raison, l'utilisation de C # 8.0 n'est prise en charge que sur les plates-formes qui implémentent .NET Standard 2.1.

... qui, si cela était vrai, aurait exclu l'utilisation de C # 8 avec la version any du .NET Framework, et même dans les bibliothèques .NET Standard 2.0 que nous avons récemment été encouragés à utiliser comme cible de référence pour le code de bibliothèque. Vous ne pourriez même pas l'utiliser avec des versions de .NET Core antérieures à 3.0, car elles ne prennent également en charge que .NET Standard 2.0.

L'enquête était ouverte! -

  • Jon Skeet a une version alpha de Noda-Time utilisant C # 8 prêt à l'emploi qui cible uniquement .NET Standard 2.0. Il s'attend clairement à ce que C # 8/.NET Standard 2.0 prenne en charge tous les frameworks de la famille .NET. (Voir aussi le blog de Jon "Premiers pas avec les types de référence nullables" ).

  • Les employés de Microsoft ont discuté de l'interface utilisateur de Visual Studio pour les types de référence nullable C # 8 sur GitHub , et il est indiqué qu'ils ont l'intention de prendre en charge l'héritage csproj (format SDK pré-.NET Core csproj). Il s'agit d'une indication très forte que C # 8 sera utilisable avec le .NET Framework. [Je soupçonne qu'ils vont revenir en arrière maintenant que la liste déroulante des versions linguistiques de Visual Studio 2019 a été désactivée et que .NET a été lié à C # 7.3]

  • Peu de temps après le célèbre article de blog, un fil GitHub a discuté du support multiplateforme. Un point important qui est ressorti est que . .NET Standard 2.1 inclura un marqueur qui indique que les implémentations par défaut des interfaces sont prises en charge - la fonctionnalité nécessite une modification CLR qui ne sera jamais disponible pour le .NET Framework. Voici l'essentiel, d'Immo Landwerth, responsable de programme au sein de l'équipe .NET de Microsoft:

    Les compilateurs (tels que C #) doivent utiliser la présence de ce champ pour décider d'autoriser ou non les implémentations d'interface par défaut. Si le champ est présent, le runtime devrait pouvoir charger et exécuter le code résultant.

  • Tout cela indique que "C # 8.0 n'est pris en charge que sur les plates-formes qui implémentent .NET Standard 2.1" étant une simplification excessive, et que C # 8 prendra en charge le .NET Framework mais, comme il y a tellement d'incertitude, je demandé sur GitHub et HaloFour a répondu:

    IIRC, la seule fonctionnalité qui n'apparaîtra certainement pas sur .NET Framework est DIM (méthodes d'interface par défaut) car cela nécessite des modifications d'exécution. Les autres fonctionnalités sont déterminées par la forme des classes qui pourraient ne jamais être ajoutées au .NET Framework mais peuvent être remplies par le biais de votre propre code ou NuGet (plages, index, itérateurs asynchrones, élimination asynchrone).

  • Victor Derks a commenté que "Les nouveaux attributs nullables requis pour concevoir les cas d'utilisation nullables plus complexes ne sont disponibles que dans System.Runtime.dll fourni avec .NET Core 3.0 et. NET Standard 2.1 ... [et] incompatible avec .NET Framework 4.8 "

  • Cependant, Immo Landwerth a commenté que "la grande majorité de nos API n'a pas besoin d'attributs personnalisés car les types sont soit entièrement génériques soit non nuls" sous l'article Essayez la référence nullable Types

  • Ben Hall a soulevé la question Disponibilité des attributs nullables en dehors de Core 3. sur GitHub, avec les commentaires suivants des employés de Microsoft à noter:

C # 8 sera entièrement pris en charge sur .net core 3.0 et .net standard 2.1 uniquement. Si vous modifiez manuellement le fichier de projet pour utiliser C # 8 avec .net core 2.1, vous êtes en territoire non pris en charge. Certaines fonctionnalités C # 8 fonctionneront bien, certaines fonctionnalités C # 8 ne fonctionneront pas trop bien (par exemple, de mauvaises performances), certaines fonctionnalités C # 8 fonctionneront avec des hacks supplémentaires et certaines fonctionnalités C # 8 ne fonctionneront pas du tout. Très complexe à expliquer. Nous ne le bloquons pas activement afin que les utilisateurs experts qui peuvent le parcourir puissent le faire. Je ne recommanderais pas ce mix & match non pris en charge à utiliser largement.

(Jan Kotas)

Les gens comme vous qui veulent comprendre - et travailler autour d'eux - sont libres d'utiliser C # 8. Le fait est que toutes les fonctionnalités du langage ne fonctionneront pas sur des cibles de niveau inférieur.

(Immo Landwerth)


Visual Studio 2019

Il y a eu un changement majeur dans la version RTM de Visual Studio 2019 version 16.3 - la version de lancement pour C # 8.0: la liste déroulante de sélection de la langue a été désactivée:

enter image description here

justification de Microsoft est:

À l'avenir, ... chaque version de chaque framework aura une seule version prise en charge et par défaut, et nous ne prendrons pas en charge les versions arbitraires. Pour refléter ce changement de support, cette validation désactive définitivement la zone de liste déroulante des versions linguistiques et ajoute un lien vers un document expliquant le changement.

Le document qui s'ouvre est versionnage en langage C # . Cela répertorie C # 8.0 comme langue par défaut pour .NET Core 3.x UNIQUEMENT. Il confirme également que chaque version de chaque framework aura, à l'avenir, une seule version prise en charge et par défaut et que l'agnosticisme du framework du langage ne peut pas compter plus.

La version linguistique peut toujours être forcée à 8 pour les projets .NET Framework en modifiant le fichier .csproj.


Caveat emptor

La combinaison C # 8/.NET Framework n'est pas officiellement prise en charge par Microsoft. C'est, disent-ils, uniquement pour les experts.

163
Stephen Kennedy

Selon cette entrée de blog la langue est en effet liée au framework:

Cela signifie que les types requis pour utiliser ces fonctionnalités ne seront pas disponibles sur .NET Framework 4.8. De même, les implémentations des membres d'interface par défaut reposent sur de nouvelles améliorations d'exécution, et nous ne les apporterons pas non plus dans .NET Runtime 4.8.

Pour cette raison, l'utilisation de C # 8.0 n'est prise en charge que sur les plates-formes qui implémentent .NET Standard 2.1. La nécessité de maintenir le runtime stable nous a empêchés de mettre en œuvre de nouvelles fonctionnalités de langage en elle pendant plus d'une décennie. Avec la nature côte à côte et open-source des temps d'exécution modernes, nous pensons que nous pouvons à nouveau les faire évoluer de manière responsable, et faire la conception du langage dans cet esprit. Scott a expliqué dans sa mise à jour sur .NET Core 3.0 et .NET Framework 4.8 que .NET Framework verra moins d'innovation à l'avenir, se concentrant plutôt sur la stabilité et la fiabilité. Compte tenu de cela, nous pensons qu'il vaut mieux qu'il passe à côté de certaines fonctionnalités du langage que que personne ne les obtienne.

31
user1781290

C # 8.0 (et supérieur) n'est pris en charge que sur .NET Core 3.x et les versions plus récentes. La plupart des fonctionnalités les plus récentes nécessitent des fonctionnalités de bibliothèque et d'exécution introduites dans .NET Core 3.x: versioning en langage C #

0
Zdravko Zdravkov