Czy C # 8 obsługuje .NET Framework?

132

W ustawieniach zaawansowanej kompilacji programu Visual Studio 2019 język C # 8 nie wydaje się być dostępny dla projektu .NET Framework, tylko (jak na poniższym obrazku) dla projektu .NET Core 3.0:

wprowadź opis obrazu tutaj

Czy C # 8 obsługuje .NET Framework?

James Harcourt
źródło

Odpowiedzi:

240

Tak, języka C # 8 można używać z platformą .NET Framework i innymi elementami docelowymi starszymi niż .NET Core 3.0 / .NET Standard 2.1 w programie Visual Studio 2019 (lub starszymi wersjami programu Visual Studio, jeśli zainstalujesz pakiet Nuget ).

Wersja językowa musi być ustawiona 8.0w pliku csproj.

Większość funkcji - ale nie wszystkie - jest dostępnych niezależnie od platformy docelowej.


Funkcje, które działają

Następujące funkcje dotyczą tylko zmian składni; działają niezależnie od frameworka:

Funkcje, które mogą działać

Wymagają one nowych typów, których nie ma w programie .NET Framework. Można ich używać tylko w połączeniu z pakietami Nuget typu „polyfill” lub plikami kodu:

Domyślni członkowie interfejsu - nie działają

Domyślne elementy interfejsu nie będą kompilować się w .NET Framework i nigdy nie będą działać, ponieważ wymagają zmian w środowisku wykonawczym w środowisku CLR. .NET CLR jest teraz zamrożony, ponieważ .NET Core jest teraz drogą do przodu.

Aby uzyskać więcej informacji na temat tego, co działa, a co nie, a także na temat możliwych polyfillów, zobacz artykuł Stuarta Langa, C # 8.0 i .NET Standard 2.0 - Doing Unsupported Things .


Kod

Poniższy projekt w języku C # jest przeznaczony dla programu .NET Framework 4.8 i przy użyciu typów odwołań dopuszczających wartość null w języku C # 8 kompiluje się w programie Visual Studio 16.2.0. Utworzyłem go, wybierając szablon .NET Standard Class Library, a następnie edytując go pod kątem .NET Framework:

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

Następnie wypróbowałem projekt .NET Framework 4.5.2 WinForms, używając starszego .csprojformatu i dodałem tę samą właściwość typu odwołania dopuszczającego wartość null. Zmieniłem typ języka w oknie dialogowym ustawień Visual Studio Advanced Build (wyłączone w 16.3) latesti zapisałem projekt. Oczywiście w tym momencie nie buduje się. Otworzyłem plik projektu w edytorze tekstu i zmieniłem latestna previeww konfiguracji kompilacji PropertyGroup:

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

Następnie włączyłem obsługę typów odwołań dopuszczających wartość null, dodając <Nullable>enable</Nullable>do pliku main PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Ponownie załadowałem projekt i kompiluje się.


Krwawe szczegóły

Kiedy ta odpowiedź została napisana po raz pierwszy, C # 8 był w wersji zapoznawczej i wymagało dużo pracy detektywa. Zostawiam tę informację tutaj dla potomności. Możesz go pominąć, jeśli nie musisz znać wszystkich krwawych szczegółów.

Język C # był historycznie w większości neutralny dla frameworka - tj. Zdolny do kompilowania starszych wersji frameworka - chociaż niektóre funkcje wymagały nowych typów lub obsługi CLR.

Większość entuzjastów C # przeczyta wpis na blogu Building C # 8.0 autorstwa Madsa Torgersena, w którym wyjaśniono, że niektóre funkcje C # 8 mają zależności od platformy:

Strumienie asynchroniczne, indeksatory i zakresy opierają się na nowych typach platform, które będą częścią .NET Standard 2.1 ... .NET Core 3.0, a także Xamarin, Unity i Mono będą implementować .NET Standard 2.1, ale .NET Framework 4.8 będzie nie. Oznacza to, że typy wymagane do korzystania z tych funkcji nie będą dostępne w programie .NET Framework 4.8.

Wygląda to trochę jak krotki wartości, które zostały wprowadzone w C # 7. Ta funkcja wymagała nowych typów - ValueTuplestruktur - które nie były dostępne w wersjach NET Framework poniżej 4,7 lub .NET Standard starszych niż 2,0. Jednak języka C # 7 można nadal używać w starszych wersjach platformy .NET, bez krotek wartości lub z nimi, instalując pakiet System.ValueTuple Nuget . Visual Studio to zrozumiało i ze światem wszystko było w porządku.

Jednak Mads napisał również:

Z tego powodu używanie języka C # 8.0 jest obsługiwane tylko na platformach implementujących .NET Standard 2.1.

... co, gdyby było prawdziwe, wykluczyłoby używanie C # 8 z dowolną wersją .NET Framework, a nawet w bibliotekach .NET Standard 2.0, których dopiero niedawno zachęcono nas do użycia jako podstawowego celu dla kodu biblioteki. Nie można go nawet używać z wersjami .NET Core starszymi niż 3.0, ponieważ one również obsługują tylko .NET Standard 2.0.

Śledztwo trwało! -

  • Jon Skeet ma wersję alfa Noda-Time używającą C # 8 gotową do pracy, która jest przeznaczona tylko dla .NET Standard 2.0. Wyraźnie oczekuje, że C # 8 / .NET Standard 2.0 będzie obsługiwał wszystkie frameworki z rodziny .NET. (Zobacz także post Jona „Pierwsze kroki z typami odwołań dopuszczających wartość null” ).

  • Pracownicy firmy Microsoft omawiali interfejs użytkownika programu Visual Studio dla typów odwołań dopuszczających wartość null w języku C # 8 w witrynie GitHub i stwierdzono, że zamierzają obsługiwać csprojstarszą wersję (format zestawu SDK sprzed wersji .NET Core csproj). To bardzo mocna wskazówka, że ​​język C # 8 będzie działał z platformą .NET Framework. [Podejrzewam, że wycofają się z tego teraz, gdy lista rozwijana wersji językowej programu Visual Studio 2019 została wyłączona, a platforma .NET została powiązana z C # 7.3]

  • Krótko po słynnym wpisie na blogu w wątku GitHub omówiono obsługę wielu platform. Ważnym punktem, który się pojawił, było to, że .NET Standard 2.1 będzie zawierał znacznik wskazujący, że obsługiwane są domyślne implementacje interfejsów - funkcja wymaga zmiany CLR, która nigdy nie będzie dostępna dla .NET Framework. Oto ważny fragment od Immo Landwerth, menedżera programu w zespole .NET w firmie Microsoft:

    Kompilatory (takie jak C #) powinny używać obecności tego pola, aby zdecydować, czy zezwolić na domyślne implementacje interfejsu. Jeśli pole jest obecne, oczekuje się, że środowisko wykonawcze będzie w stanie załadować i wykonać wynikowy kod.

  • To wszystko wskazywało na to, że „C # 8.0 jest obsługiwany tylko na platformach, które implementują .NET Standard 2.1” jest nadmiernym uproszczeniem i że C # 8 będzie obsługiwał .NET Framework, ale ponieważ jest tak wiele niepewności, zapytałem na GitHub, a HaloFour odpowiedział:

    IIRC, jedyną funkcją, która na pewno nie pojawi się w .NET Framework, jest DIM (domyślne metody interfejsu), ponieważ wymaga zmian w czasie wykonywania. Inne funkcje są sterowane kształtem klas, które mogą nigdy nie zostać dodane do platformy .NET Framework, ale mogą zostać wypełnione za pomocą własnego kodu lub pakietu NuGet (zakresy, indeksy, iteratory asynchroniczne, usuwanie asynchroniczne).

  • Victor Derks skomentował, że „ Nowe atrybuty dopuszczające wartość null wymagane do projektowania bardziej złożonych przypadków użycia dopuszczających wartość null są dostępne tylko w bibliotece System.Runtime.dll dostarczanej z platformami .NET Core 3.0 i .NET Standard 2.1 ... [i] niezgodnych z .NET Framework 4,8 "

  • Jednak firma Immo Landwerth skomentowała, że „Zdecydowana większość naszych interfejsów API nie potrzebowała żadnych niestandardowych atrybutów, ponieważ typy są albo w pełni ogólne, albo niezerowe” w artykule Wypróbuj typy odwołań zerujących

  • Ben Hall poruszył kwestię Dostępność atrybutów dopuszczających wartość null poza Core 3.0 na GitHub, zwracając uwagę na następujące komentarze pracowników Microsoft:

C # 8 będzie w pełni obsługiwany tylko w .net core 3.0 i .net standard 2.1. Jeśli ręcznie edytujesz plik projektu, aby używać C # 8 z .net core 2.1, znajdujesz się na nieobsługiwanym terytorium. Niektóre funkcje C # 8 będą działać dobrze, niektóre funkcje C # 8 nie będą działać zbyt dobrze (np. Słaba wydajność), niektóre funkcje C # 8 będą działać z dodatkowymi hackami, a niektóre funkcje C # 8 nie będą działać w ogóle. Bardzo trudne do wyjaśnienia. Nie blokujemy go aktywnie, więc eksperci, którzy mogą się po nim poruszać, mogą to zrobić. Nie polecam szerokiego stosowania tego nieobsługiwanego połączenia i dopasowania.

(Jan Kotas)

Osoby takie jak Ty, które chcą je zrozumieć - i obejść je - mogą swobodnie używać języka C # 8. Chodzi o to, że nie wszystkie funkcje języka będą działać na niższych poziomach docelowych.

(Immo Landwerth)


Visual Studio 2019

Nastąpiła poważna zmiana w wersji RTM programu Visual Studio 2019 w wersji 16.3 - wersja uruchomieniowa dla C # 8.0: lista rozwijana wyboru języka została wyłączona:

wprowadź opis obrazu tutaj

Uzasadnieniem firmy Microsoft jest:

Idąc dalej, ... każda wersja każdego frameworka będzie miała jedną obsługiwaną i domyślną wersję i nie będziemy obsługiwać dowolnych wersji. Aby odzwierciedlić tę zmianę w obsłudze, to zatwierdzenie na stałe wyłącza pole kombi wersji językowej i dodaje łącze do dokumentu wyjaśniającego zmianę.

Dokument, który zostanie otwarty, to wersja językowa C # . Ta lista zawiera język C # 8.0 jako język domyślny TYLKO dla platformy .NET Core 3.x. Potwierdza również, że każda wersja każdego frameworka będzie w przyszłości mieć jedną obsługiwaną i domyślną wersję oraz że nie można już polegać na agnostycyzmie języka.

W przypadku projektów .NET Framework nadal można zmienić wersję językową na 8, edytując plik .csproj.


Caveat emptor

Połączenie C # 8 / .NET Framework nie jest oficjalnie obsługiwane przez firmę Microsoft. Mówią, że jest to tylko dla ekspertów.

Stephen Kennedy
źródło
3
To powinno wyjaśnić wszelkie nieporozumienia wynikającego z faktu, możemy, jeśli spróbujemy użyć niektóre funkcje C # 8 poza standardem 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall
2
Nowe atrybuty dopuszczające wartość null ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ) wymagane do projektowania bardziej złożonych przypadków użycia dopuszczających wartość null są dostępne tylko w System.Runtime.dll dostarczanym z .NET Core 3.0 i. NET Standard 2.1. To sprawia, że ​​nullable \ C # 8.0 jest niezgodne z programem .NET Framework 4.8
Victor Derks,
3
@BenHall Dodałem kilka wniosków z twojego problemu - bardzo dziękuję za zgłoszenie problemu i za umieszczenie tutaj. Prosimy o edycję odpowiedzi, jeśli jest w jakikolwiek sposób niepoprawna.
Stephen Kennedy
3
Visual Studio 2019 IntelliSense nie obsługuje typów odwołań dopuszczających wartość null, gdy są określone <Nullable>enable</Nullable>w csproj. Wydaje się, że działa, gdy używa się #nullable enabledyrektyw. Zobacz też: github.com/dotnet/project-system/issues/5551
Bouke
3
@odalet Nie miałbym żadnych skrupułów, celując w C # 8 i używając podstawowych funkcji, które nie wymagają polyfillów (już to robię), a być może także z polyfillami (nie potrzebowałem ich). Jednak najlepszą radą, jaką mogę być, jest: jeśli masz wątpliwości, nie rób tego, przynajmniej nie, jeśli zależy od tego twoja praca.
Stephen Kennedy
34

Według tego wpisu na blogu język jest rzeczywiście powiązany z ramami:

Oznacza to, że typy wymagane do korzystania z tych funkcji nie będą dostępne w programie .NET Framework 4.8. Podobnie, domyślne implementacje elementów składowych interfejsu opierają się na nowych ulepszeniach środowiska wykonawczego, a my nie wprowadzimy ich również w .NET Runtime 4.8.

Z tego powodu używanie języka C # 8.0 jest obsługiwane tylko na platformach implementujących .NET Standard 2.1. Potrzeba utrzymania stabilnego środowiska wykonawczego uniemożliwiła nam wdrażanie w nim nowych funkcji językowych przez ponad dekadę. Biorąc pod uwagę współistnienie i otwartoźródłowy charakter nowoczesnych środowisk wykonawczych, czujemy, że możemy je ponownie odpowiedzialnie rozwijać i mając to na uwadze, projektować język. Scott wyjaśnił w swojej aktualizacji dotyczącej .NET Core 3.0 i .NET Framework 4.8, że .NET Framework zobaczy w przyszłości mniej innowacji, zamiast tego skupi się na stabilności i niezawodności. Biorąc to pod uwagę, uważamy, że lepiej jest przegapić niektóre funkcje językowe, niż nikogo, kto je otrzyma.

user1781290
źródło
3
O wiele więcej szczegółów w innej odpowiedzi Stephena Kennedy'ego. W rzeczywistości dość łatwo jest sprawić, aby znaczny podzbiór C # 8.0 działał, gdy jest przeznaczony na platformę .NET Framework. Jednak niektóre części C # 8.0 wymagają zmian w środowisku wykonawczym, których Microsoft nie zamierza wprowadzać dla „starego” .NET Framework. Wydaje się, że są one ściślej związane ze sobą wersją językową i wersją .NET.
Jeppe Stig Nielsen
1

C # 8.0 (i nowsze) jest obsługiwany tylko w .NET Core 3.xi nowszych wersjach. Wiele najnowszych funkcji wymaga bibliotek i funkcji środowiska uruchomieniowego wprowadzonych w .NET Core 3.x: C # do obsługi wersji językowych

Zdravko Zdravkov
źródło
3
Czy widzisz powyżej oznaczoną jako poprawną odpowiedź od @stephen kennedy?
James Harcourt