C # 8 supporta .NET Framework?


131

Nelle impostazioni di compilazione avanzata di Visual Studio 2019, C # 8 non sembra essere disponibile per un progetto .NET Framework, solo (come nell'immagine seguente) per un progetto .NET Core 3.0:

inserisci qui la descrizione dell'immagine

C # 8 supporta .NET Framework?

Risposte:


238

Sì, C # 8 può essere usato con .NET Framework e altre destinazioni precedenti a .NET Core 3.0 / .NET Standard 2.1 in Visual Studio 2019 (o versioni precedenti di Visual Studio se si installa un pacchetto Nuget ).

La versione della lingua deve essere impostata su 8.0nel file csproj.

La maggior parte, ma non tutte, le funzionalità sono disponibili a prescindere dal framework scelto.


Caratteristiche che funzionano

Le seguenti funzionalità sono solo modifiche alla sintassi; funzionano indipendentemente dal framework:

Caratteristiche che possono essere fatte funzionare

Questi richiedono nuovi tipi che non sono in .NET Framework. Possono essere utilizzati solo insieme ai pacchetti Nuget "polyfill" o ai file di codice:

Membri dell'interfaccia predefinita: non funzionano

I membri dell'interfaccia predefinita non verranno compilati in .NET Framework e non funzioneranno mai perché richiedono modifiche di runtime in CLR. .NET CLR è ora congelato poiché .NET Core è ora la via da seguire.

Per ulteriori informazioni su cosa funziona e cosa non funziona e sui possibili polyfill, vedere l'articolo di Stuart Lang, C # 8.0 e .NET Standard 2.0 - Doing Unsupported Things .


Codice

Il progetto C # seguente destinato a .NET Framework 4.8 e all'uso di tipi di riferimento nullable C # 8 viene compilato in Visual Studio 16.2.0. L'ho creato scegliendo il modello .NET Standard Class Library e quindi modificandolo per targetizzare .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; }
    }
}

Ho quindi provato un progetto .NET Framework 4.5.2 WinForms, utilizzando un .csprojformato legacy , e ho aggiunto la stessa proprietà del tipo di riferimento nullable. Ho cambiato il tipo di lingua nella finestra di dialogo delle impostazioni di compilazione avanzate di Visual Studio (disabilitata in 16.3) lateste ho salvato il progetto. Naturalmente come questo punto non si costruisce. Ho aperto il file di progetto in un editor di testo e sono passato latesta previewnella configurazione della build PropertyGroup:

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

Ho quindi abilitato il supporto per i tipi di riferimento nullable aggiungendo <Nullable>enable</Nullable>al main PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Ho ricaricato il progetto e si costruisce.


I dettagli cruenti

Quando questa risposta è stata scritta per la prima volta, C # 8 era in anteprima ed era coinvolto molto lavoro investigativo. Lascio queste informazioni qui per i posteri. Sentiti libero di saltarlo se non hai bisogno di conoscere tutti i dettagli cruenti.

Il linguaggio C # è stato storicamente per lo più neutro rispetto al framework , ovvero in grado di compilare versioni precedenti del Framework, sebbene alcune funzionalità abbiano richiesto nuovi tipi o supporto CLR.

La maggior parte degli appassionati di C # avrà letto il post sul blog Building C # 8.0 di Mads Torgersen, che spiega che alcune funzionalità di C # 8 hanno dipendenze dalla piattaforma:

I flussi asincroni, gli indicizzatori e gli intervalli si basano tutti su nuovi tipi di framework che faranno parte di .NET Standard 2.1 ... .NET Core 3.0 così come Xamarin, Unity e Mono implementeranno .NET Standard 2.1, ma .NET Framework 4.8 lo farà non. Ciò significa che i tipi richiesti per utilizzare queste funzionalità non saranno disponibili in .NET Framework 4.8.

Questo assomiglia un po 'alle tuple di valore introdotte in C # 7. Quella funzionalità richiedeva nuovi tipi, le ValueTuplestrutture, che non erano disponibili nelle versioni di NET Framework inferiori a 4.7 o .NET Standard precedenti alla 2.0. Tuttavia , C # 7 potrebbe ancora essere usato nelle versioni precedenti di .NET, senza tuple di valore o con esse installando il pacchetto System.ValueTuple Nuget . Visual Studio lo ha capito e tutto andava bene nel mondo.

Tuttavia, Mads ha anche scritto:

Per questo motivo, l'utilizzo di C # 8.0 è supportato solo su piattaforme che implementano .NET Standard 2.1.

... che se fosse vero avrebbe escluso l'uso di C # 8 con qualsiasi versione di .NET Framework, e in effetti anche nelle librerie .NET Standard 2.0 che solo di recente siamo stati incoraggiati a utilizzare come obiettivo di base per il codice della libreria. Non saresti nemmeno in grado di usarlo con le versioni .NET Core precedenti alla 3.0 in quanto supportano solo .NET Standard 2.0.

L'indagine era iniziata! -

  • Jon Skeet ha una versione alpha di Noda-Time che utilizza C # 8 pronta per l'uso, destinata solo a .NET Standard 2.0. Si aspetta chiaramente che C # 8 / .NET Standard 2.0 supporti tutti i framework della famiglia .NET. (Vedere anche il post del blog di Jon "Primi passaggi con tipi di riferimento nullable" ).

  • I dipendenti Microsoft hanno discusso dell'interfaccia utente di Visual Studio per i tipi di riferimento nullable C # 8 su GitHub e si afferma che intendono supportare la versione legacy csproj(formato pre- .NET Core SDK csproj). Questa è un'indicazione molto forte che C # 8 sarà utilizzabile con .NET Framework. [Sospetto che torneranno indietro su questo punto ora che l'elenco a discesa della versione della lingua di Visual Studio 2019 è stato disabilitato e .NET è stato collegato a C # 7.3]

  • Poco dopo il famoso post del blog, un thread di GitHub ha discusso del supporto multipiattaforma. Un punto importante emerso è stato che .NET Standard 2.1 includerà un indicatore che denota il supporto delle implementazioni predefinite delle interfacce : la funzionalità richiede una modifica CLR che non sarà mai disponibile per .NET Framework. Ecco la parte importante, di Immo Landwerth, Program Manager del team .NET di Microsoft:

    I compilatori (come C #) dovrebbero utilizzare la presenza di questo campo per decidere se consentire o meno le implementazioni dell'interfaccia predefinita. Se il campo è presente, il runtime dovrebbe essere in grado di caricare ed eseguire il codice risultante.

  • Tutto ciò indicava che "C # 8.0 è supportato solo su piattaforme che implementano .NET Standard 2.1" è una semplificazione eccessiva e che C # 8 supporterà .NET Framework ma, poiché c'è così tanta incertezza, ho chiesto a GitHub e HaloFour ha risposto:

    IIRC, l'unica caratteristica che sicuramente non apparirà su .NET Framework è DIM (metodi di interfaccia predefiniti) in quanto richiede modifiche al runtime. Le altre funzionalità sono guidate dalla forma delle classi che potrebbero non essere mai aggiunte a .NET Framework ma che possono essere riempite tramite il tuo codice o NuGet (intervalli, indici, iteratori asincroni, eliminazione asincrona).

  • Victor Derks ha commentato che "I nuovi attributi nullable richiesti per progettare i casi d'uso nullable più complessi sono disponibili solo in System.Runtime.dll fornito con .NET Core 3.0 e .NET Standard 2.1 ... [e] incompatibili con .NET Framework 4.8"

  • Tuttavia, Immo Landwerth ha commentato che "La stragrande maggioranza delle nostre API non necessitava di attributi personalizzati in quanto i tipi sono completamente generici o non nulli" nell'articolo Prova i tipi di riferimento nullable

  • Ben Hall ha sollevato il problema Disponibilità di attributi nullable al di fuori di Core 3.0 su GitHub, con i seguenti commenti dei dipendenti Microsoft da notare:

C # 8 sarà completamente supportato solo su .net core 3.0 e .net standard 2.1. Se modifichi manualmente il file di progetto per utilizzare C # 8 con .net core 2.1, ti trovi in ​​un territorio non supportato. Alcune funzionalità di C # 8 funzioneranno bene, alcune funzionalità di C # 8 non funzioneranno molto bene (ad esempio prestazioni scarse), alcune funzionalità di C # 8 funzioneranno con hack aggiuntivi e alcune funzionalità di C # 8 non funzioneranno affatto. Molto complesso da spiegare. Non lo blocciamo attivamente in modo che gli utenti esperti che possono navigare attraverso di esso possano farlo. Non consiglierei che questo mix & match non supportato venga utilizzato ampiamente.

(Jan Kotas)

Le persone come te che sono disposte a capire - e aggirarle - sono libere di usare C # 8. Il punto è che non tutte le funzionalità del linguaggio funzioneranno su obiettivi di livello inferiore.

(Immo Landwerth)


Visual Studio 2019

C'è stato un cambiamento importante nella versione RTM di Visual Studio 2019 versione 16.3, la versione di lancio per C # 8.0: il menu a discesa di selezione della lingua è stato disabilitato:

inserisci qui la descrizione dell'immagine

La logica di Microsoft per questo è:

Andando avanti, ... ogni versione di ogni framework avrà una singola versione supportata e predefinita e non supporteremo versioni arbitrarie. Per riflettere questa modifica nel supporto, questo commit disabilita permanentemente la casella combinata della versione della lingua e aggiunge un collegamento a un documento che spiega la modifica.

Il documento che si apre è versioni in linguaggio C # . Questo elenca C # 8.0 come lingua predefinita SOLO per .NET Core 3.x. Conferma inoltre che ogni versione di ciascun framework, in futuro, avrà una singola versione supportata e predefinita e che non è più possibile fare affidamento sull'agnosticismo del linguaggio.

La versione della lingua può ancora essere forzata a 8 per i progetti .NET Framework modificando il file .csproj.


Avvertimento emptor

La combinazione C # 8 / .NET Framework non è ufficialmente supportata da Microsoft. È, dicono, solo per esperti.


3
Questo dovrebbe eliminare ogni confusione derivante dal fatto che possiamo, se proviamo, utilizzare alcune funzionalità C # 8 al di fuori dello Standard 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall

2
I nuovi attributi nullable ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ) richiesti per progettare i casi d'uso nullable più complessi sono disponibili solo in System.Runtime.dll fornito con .NET Core 3.0 e. NET Standard 2.1. Ciò rende nullable \ C # 8.0 incompatibile con NET Framework 4.8
Victor Derks

3
@ BenHall Ho aggiunto alcuni suggerimenti dal tuo problema: grazie mille per aver sollevato il problema e per aver postato qui. Sentiti libero di modificare la risposta se è in qualche modo errata.
Stephen Kennedy

3
Visual Studio 2019 IntelliSense non supporta i tipi di riferimento nullable quando specificato attraverso <Nullable>enable</Nullable>la csproj. Sembra funzionare quando si usano le #nullable enabledirettive. Vedi anche: github.com/dotnet/project-system/issues/5551
Bouke

3
@odalet Non avrei problemi a prendere di mira C # 8 e utilizzare le funzionalità di base che non richiedono polyfill (già lo fanno), e forse anche con i polyfill (non ne ho avuto bisogno). Tuttavia, il miglior consiglio che posso essere è: in caso di dubbio, non farlo, almeno non se il tuo lavoro dipende da questo.
Stephen Kennedy,

34

Secondo questo post di blog la lingua è infatti legata al framework:

Ciò significa che i tipi richiesti per utilizzare queste funzionalità non saranno disponibili in .NET Framework 4.8. Allo stesso modo, le implementazioni dei membri dell'interfaccia predefinita si basano su nuovi miglioramenti del runtime e non li realizzeremo neanche in .NET Runtime 4.8.

Per questo motivo, l'utilizzo di C # 8.0 è supportato solo su piattaforme che implementano .NET Standard 2.1. La necessità di mantenere stabile il runtime ci ha impedito di implementare nuove funzionalità del linguaggio in esso per più di un decennio. Con la natura side-by-side e open-source dei runtime moderni, riteniamo di poterli evolvere di nuovo in modo responsabile e progettare il linguaggio con questo in mente. Scott ha spiegato nel suo aggiornamento su .NET Core 3.0 e .NET Framework 4.8 che .NET Framework vedrà meno innovazione in futuro, concentrandosi invece su stabilità e affidabilità. Detto questo, riteniamo che sia meglio perdere alcune funzionalità del linguaggio piuttosto che nessuno le ottiene.


3
Molti altri dettagli nell'altra risposta di Stephen Kennedy. In effetti, è abbastanza facile far funzionare un sottoinsieme sostanziale di C # 8.0 quando si utilizza .NET Framework. Ma alcune parti di C # 8.0 richiedono modifiche al runtime che Microsoft non apporterà al "vecchio" .NET Framework. E sembrano legare più strettamente la versione in lingua e la versione .NET.
Jeppe Stig Nielsen

1

C # 8.0 (e versioni successive) è supportato solo in .NET Core 3.xe versioni successive. Molte delle funzionalità più recenti richiedono funzionalità di libreria e runtime introdotte in .NET Core 3.x: controllo delle versioni in linguaggio C #


2
Hai visto la risposta contrassegnata come corretta da @stephen kennedy sopra?
James Harcourt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.