Unterstützt C # 8 .NET Framework?

126

In den erweiterten Build-Einstellungen von Visual Studio 2019 scheint C # 8 nicht für ein .NET Framework-Projekt verfügbar zu sein, sondern nur (wie in der folgenden Abbildung) für ein .NET Core 3.0-Projekt:

Geben Sie hier die Bildbeschreibung ein

Unterstützt C # 8 .NET Framework?

James Harcourt
quelle

Antworten:

229

Ja, C # 8 kann mit .NET Framework und anderen Zielen verwendet werden, die älter als .NET Core 3.0 / .NET Standard 2.1 in Visual Studio 2019 sind (oder ältere Versionen von Visual Studio, wenn Sie ein Nuget-Paket installieren ).

Die Sprachversion muss 8.0in der csproj-Datei eingestellt sein.

Die meisten - aber nicht alle - Funktionen sind verfügbar, je nachdem, welches Framework angestrebt wird.


Funktionen, die funktionieren

Die folgenden Funktionen sind nur Syntaxänderungen. Sie arbeiten unabhängig vom Rahmen:

Funktionen, die zum Funktionieren gebracht werden können

Diese erfordern neue Typen, die nicht in .NET Framework enthalten sind. Sie können nur in Verbindung mit "Polyfill" -Nuget-Paketen oder Codedateien verwendet werden:

Standardschnittstellenmitglieder - funktionieren nicht

Standardschnittstellenmitglieder werden unter .NET Framework nicht kompiliert und funktionieren nie, da sie Laufzeitänderungen in der CLR erfordern. Die .NET CLR ist jetzt eingefroren, da .NET Core jetzt der richtige Weg ist.

Weitere Informationen dazu, was funktioniert und was nicht, und zu möglichen Polyfills finden Sie in Stuart Langs Artikel C # 8.0 und .NET Standard 2.0 - Nicht unterstützte Aufgaben .


Code

Das folgende C # -Projekt, das auf .NET Framework 4.8 abzielt und C # 8-nullfähige Referenztypen verwendet, wird in Visual Studio 16.2.0 kompiliert. Ich habe es erstellt, indem ich die .NET Standard Class Library-Vorlage ausgewählt und sie stattdessen so bearbeitet habe, dass sie auf .NET Framework abzielt:

.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; }
    }
}

Ich habe dann ein WinForms-Projekt mit .NET Framework 4.5.2 unter Verwendung eines Legacy- .csprojFormats ausprobiert und dieselbe nullfähige Referenztyp-Eigenschaft hinzugefügt. Ich habe den Sprachtyp im Dialogfeld "Erweiterte Build-Einstellungen für Visual Studio" (in 16.3 deaktiviert) in geändert latestund das Projekt gespeichert. Natürlich baut es an diesem Punkt nicht auf. Ich öffnete die Projektdatei in einem Texteditor und geändert , latestum previewin der Build - Konfiguration PropertyGroup:

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

Ich habe dann die Unterstützung für nullfähige Referenztypen aktiviert, indem ich Folgendes hinzugefügt <Nullable>enable</Nullable>habe PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Ich habe das Projekt neu geladen und es wird erstellt.


Die blutigen Details

Als diese Antwort zum ersten Mal geschrieben wurde, war C # 8 in der Vorschau und es war viel Detektivarbeit erforderlich. Ich lasse diese Informationen hier für die Nachwelt. Sie können es gerne überspringen, wenn Sie nicht alle wichtigen Details kennen müssen.

Die C # -Sprache war in der Vergangenheit größtenteils Framework-neutral - dh sie konnte ältere Versionen des Frameworks kompilieren - obwohl für einige Funktionen neue Typen oder CLR-Unterstützung erforderlich waren.

Die meisten C # -Enthusiasten haben den Blogeintrag Building C # 8.0 von Mads Torgersen gelesen , in dem erklärt wird, dass bestimmte Funktionen von C # 8 plattformabhängig sind:

Asynchrone Streams, Indexer und Bereiche basieren alle auf neuen Framework-Typen, die Teil von .NET Standard 2.1 sein werden. .NET Core 3.0 sowie Xamarin, Unity und Mono werden .NET Standard 2.1 implementieren, .NET Framework 4.8 jedoch nicht. Dies bedeutet, dass die zur Verwendung dieser Funktionen erforderlichen Typen in .NET Framework 4.8 nicht verfügbar sind.

Dies ähnelt ein wenig den in C # 7 eingeführten Wertetupeln . Für diese Funktion waren neue Typen erforderlich - die ValueTupleStrukturen -, die in NET Framework-Versionen unter 4.7 oder .NET Standard älter als 2.0 nicht verfügbar waren. Allerdings , C # 7 könnte noch in älteren Versionen von .NET verwendet werden, entweder ohne Wertetupeln oder mit ihnen durch die Installation System.ValueTuple Nuget Pakets . Visual Studio hat das verstanden und alles war in Ordnung mit der Welt.

Mads schrieb jedoch auch:

Aus diesem Grund wird die Verwendung von C # 8.0 nur auf Plattformen unterstützt, die .NET Standard 2.1 implementieren.

... was, wenn dies zutrifft, die Verwendung von C # 8 mit jeder Version von .NET Framework und sogar in .NET Standard 2.0-Bibliotheken ausgeschlossen hätte, die wir erst kürzlich als Basisziel für Bibliothekscode verwenden sollten. Sie können es nicht einmal mit .NET Core-Versionen verwenden, die älter als 3.0 sind, da auch diese nur .NET Standard 2.0 unterstützen.

Die Untersuchung war eröffnet! - -

  • Jon Skeet hat eine Alpha-Version von Noda-Time mit C # 8 bereit, die nur auf .NET Standard 2.0 abzielt. Er erwartet eindeutig, dass C # 8 / .NET Standard 2.0 alle Frameworks in der .NET-Familie unterstützt. (Siehe auch Jons Blog-Beitrag "Erste Schritte mit nullbaren Referenztypen" ).

  • Microsoft-Mitarbeiter haben die Visual Studio-Benutzeroberfläche für nullwertfähige C # 8-Referenztypen auf GitHubcsproj erörtert , und es wird angegeben, dass sie beabsichtigen, das Legacy (Pre-.NET Core SDK-Format csproj) zu unterstützen. Dies ist ein sehr starker Hinweis darauf, dass C # 8 mit .NET Framework verwendet werden kann. [Ich vermute, dass sie dies jetzt zurückverfolgen werden, da das Dropdown-Menü für die Sprachversion von Visual Studio 2019 deaktiviert und .NET an C # 7.3 gebunden wurde.]

  • Kurz nach dem berühmten Blog-Beitrag diskutierte ein GitHub-Thread die plattformübergreifende Unterstützung. Ein wichtiger Punkt, der sich herausstellte, war, dass .NET Standard 2.1 eine Markierung enthält, die angibt, dass Standardimplementierungen von Schnittstellen unterstützt werden. Für diese Funktion ist eine CLR-Änderung erforderlich, die für .NET Framework niemals verfügbar sein wird. Hier ist das Wichtige von Immo Landwerth, Programmmanager im .NET-Team von Microsoft:

    Von Compilern (z. B. C #) wird erwartet, dass sie das Vorhandensein dieses Felds verwenden, um zu entscheiden, ob Standardschnittstellenimplementierungen zulässig sind oder nicht. Wenn das Feld vorhanden ist, wird erwartet, dass die Laufzeit den resultierenden Code laden und ausführen kann.

  • Dies alles deutete darauf hin, dass "C # 8.0 nur auf Plattformen unterstützt wird, die .NET Standard 2.1 implementieren", was eine übermäßige Vereinfachung darstellt, und dass C # 8 .NET Framework unterstützt, aber da es so viel Unsicherheit gibt, fragte ich GitHub und HaloFour antwortete:

    IIRC, die einzige Funktion, die in .NET Framework definitiv nicht angezeigt wird, ist DIM (Standardschnittstellenmethoden), da dies Laufzeitänderungen erfordert. Die anderen Funktionen werden durch die Form von Klassen gesteuert, die möglicherweise nie zu .NET Framework hinzugefügt werden, aber über Ihren eigenen Code oder NuGet (Bereiche, Indizes, asynchrone Iteratoren, asynchrone Entsorgung) polygefüllt werden können.

  • Victor Derks kommentierte: "Die neuen nullbaren Attribute, die zum Entwerfen der komplexeren nullbaren Anwendungsfälle erforderlich sind, sind nur in System.Runtime.dll verfügbar, das mit .NET Core 3.0 und .NET Standard 2.1 geliefert wird ... [und] nicht kompatibel mit .NET Framework 4,8 "

  • Immo Landwerth kommentierte jedoch, dass "die überwiegende Mehrheit unserer APIs keine benutzerdefinierten Attribute benötigte, da die Typen entweder vollständig generisch oder nicht null sind" unter dem Artikel Nullable Referenztypen ausprobieren

  • Ben Hall hat das Problem Verfügbarkeit nullbarer Attribute außerhalb von Core 3.0 auf GitHub angesprochen , wobei die folgenden Kommentare von Microsoft-Mitarbeitern zu beachten sind:

C # 8 wird nur unter .net Core 3.0 und .net Standard 2.1 vollständig unterstützt. Wenn Sie die Projektdatei manuell bearbeiten, um C # 8 mit .net Core 2.1 zu verwenden, befinden Sie sich in einem nicht unterstützten Gebiet. Einige C # 8-Funktionen funktionieren gut, einige C # 8-Funktionen funktionieren nicht so gut (z. B. schlechte Leistung), einige C # 8-Funktionen funktionieren mit zusätzlichen Hacks und einige C # 8-Funktionen funktionieren überhaupt nicht. Sehr komplex zu erklären. Wir blockieren es nicht aktiv, damit die erfahrenen Benutzer, die darin navigieren können, dies tun können. Ich würde nicht empfehlen, dieses nicht unterstützte Mix & Match allgemein zu verwenden.

(Jan Kotas)

Menschen wie Sie, die bereit sind, sie zu verstehen - und sie zu umgehen -, können C # 8 verwenden. Der Punkt ist, dass nicht alle Sprachfunktionen auf untergeordneten Zielen funktionieren.

(Immo Landwerth)


Visual Studio 2019

In der RTM-Version von Visual Studio 2019 Version 16.3 - der Startversion für C # 8.0 - wurde eine wesentliche Änderung vorgenommen: Die Dropdown-Liste für die Sprachauswahl wurde deaktiviert:

Geben Sie hier die Bildbeschreibung ein

Microsofts Begründung hierfür lautet:

In Zukunft wird ... jede Version jedes Frameworks eine einzige unterstützte und Standardversion haben, und wir werden keine beliebigen Versionen unterstützen. Um diese Änderung in der Unterstützung widerzuspiegeln, deaktiviert dieses Commit das Kombinationsfeld für die Sprachversion dauerhaft und fügt einen Link zu einem Dokument hinzu, in dem die Änderung erläutert wird.

Das Dokument, das geöffnet wird, ist die Versionierung in C # -Sprache . Hier wird NUR C # 8.0 als Standardsprache für .NET Core 3.x aufgeführt. Es wird auch bestätigt, dass jede Version jedes Frameworks künftig eine einzige unterstützte und Standardversion haben wird und dass man sich nicht mehr auf den Framework-Agnostizismus der Sprache verlassen kann.

Die Sprachversion kann für .NET Framework-Projekte weiterhin auf 8 erzwungen werden, indem die .csproj-Datei bearbeitet wird.


Vorbehalt Emptor

Die C # 8 / .NET Framework-Kombination wird von Microsoft nicht offiziell unterstützt. Es ist, sagen sie, nur für Experten.

Stephen Kennedy
quelle
3
Dies sollte jegliche Verwirrung beseitigen, die sich aus der Tatsache ergibt, dass wir, wenn wir es versuchen, einige C # 8-Funktionen außerhalb von Standard 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall,
2
Die neuen nullbaren Attribute ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ), die zum Entwerfen der komplexeren nullbaren Anwendungsfälle erforderlich sind, sind nur in System.Runtime.dll verfügbar, das mit .NET Core 3.0 und ausgeliefert wird. NET Standard 2.1. Dies macht nullable \ C # 8.0 inkompatibel mit NET Framework 4.8
Victor Derks
3
@ BenHall Ich habe einige Imbissbuden aus Ihrer Ausgabe hinzugefügt - vielen Dank, dass Sie die Ausgabe angesprochen und hier gepostet haben. Bitte zögern Sie nicht, die Antwort zu bearbeiten, wenn sie in irgendeiner Weise falsch ist.
Stephen Kennedy
3
Visual Studio 2019 IntelliSense unterstützt keine Nullable Types Referenz , wenn angegeben durch <Nullable>enable</Nullable>in der csproj. Es scheint zu funktionieren, wenn #nullable enableDirektiven verwendet werden. Siehe auch: github.com/dotnet/project-system/issues/5551
Bouke
3
@odalet Ich hätte keine Bedenken, C # 8 ins Visier zu nehmen und die Grundfunktionen zu verwenden, für die keine Polyfills erforderlich sind (tun Sie das bereits), und möglicherweise auch für die Polyfills (haben sie nicht benötigt). Der beste Rat, den ich geben kann, ist jedoch: Wenn Sie Zweifel haben, tun Sie es nicht, zumindest nicht, wenn Ihr Job davon abhängt.
Stephen Kennedy
34

Laut diesem Blogeintrag ist die Sprache tatsächlich an das Framework gebunden:

Dies bedeutet, dass die zur Verwendung dieser Funktionen erforderlichen Typen in .NET Framework 4.8 nicht verfügbar sind. Ebenso basieren Standardimplementierungen von Schnittstellenmitgliedern auf neuen Laufzeitverbesserungen, und diese werden auch in .NET Runtime 4.8 nicht vorgenommen.

Aus diesem Grund wird die Verwendung von C # 8.0 nur auf Plattformen unterstützt, die .NET Standard 2.1 implementieren. Die Notwendigkeit, die Laufzeit stabil zu halten, hat uns mehr als ein Jahrzehnt lang daran gehindert, neue Sprachfunktionen darin zu implementieren. Angesichts des Side-by-Side- und Open-Source-Charakters der modernen Laufzeiten haben wir das Gefühl, dass wir sie verantwortungsbewusst weiterentwickeln und das Sprachdesign in diesem Sinne durchführen können. Scott erklärte in seinem Update zu .NET Core 3.0 und .NET Framework 4.8, dass .NET Framework in Zukunft weniger Innovationen sehen wird, statt sich auf Stabilität und Zuverlässigkeit zu konzentrieren. Angesichts dessen halten wir es für besser, einige Sprachfunktionen zu verpassen, als dass niemand sie erhält.

user1781290
quelle
3
Viele weitere Details in der anderen Antwort von Stephen Kennedy. Tatsächlich ist es einfach genug, eine wesentliche Teilmenge von C # 8.0 beim Targeting von .NET Framework zum Laufen zu bringen. Einige Teile von C # 8.0 erfordern jedoch Änderungen an der Laufzeit, die Microsoft für das "alte" .NET Framework nicht vornehmen wird. Und sie scheinen die Sprachversion und die .NET-Version enger miteinander zu verbinden.
Jeppe Stig Nielsen
1

C # 8.0 (und höher) wird nur unter .NET Core 3.x und neueren Versionen unterstützt. Viele der neuesten Funktionen erfordern Bibliotheks- und Laufzeitfunktionen, die in der Versionierung von .NET Core 3.x: C # eingeführt wurden

Zdravko Zdravkov
quelle
2
Haben Sie die als richtig markierte Antwort von @stephen kennedy oben gesehen?
James Harcourt