Apakah C # 8 mendukung .NET Framework?

131

Dalam pengaturan Visual Studio 2019 Advanced Build, C # 8 tampaknya tidak tersedia untuk proyek .NET Framework, hanya (seperti pada gambar di bawah) untuk proyek .NET Core 3.0:

masukkan deskripsi gambar di sini

Apakah C # 8 mendukung .NET Framework?

James Harcourt
sumber

Jawaban:

238

Ya, C # 8 dapat digunakan dengan .NET Framework dan target lain yang lebih lama dari .NET Core 3.0 / .NET Standard 2.1 di Visual Studio 2019 (atau versi Visual Studio yang lebih lama jika Anda menginstal paket Nuget ).

Versi bahasa harus disetel ke 8.0dalam file csproj.

Sebagian besar - tetapi tidak semua - fitur tersedia, kerangka mana pun yang ditargetkan.


Fitur yang berfungsi

Fitur berikut ini hanya perubahan sintaks; mereka bekerja terlepas dari kerangka kerja:

Fitur yang dapat digunakan untuk bekerja

Ini memerlukan tipe baru yang tidak ada di .NET Framework. Mereka hanya dapat digunakan bersama dengan paket Nuget "polyfill" atau file kode:

Anggota antarmuka default - tidak berfungsi

Anggota antarmuka default tidak akan dikompilasi di bawah .NET Framework dan tidak akan pernah berfungsi karena mereka memerlukan perubahan runtime di CLR. CLR .NET sekarang dibekukan karena .NET Core sekarang jalan ke depan.

Untuk informasi lebih lanjut tentang apa yang berfungsi dan tidak bekerja, dan kemungkinan polyfill, lihat artikel Stuart Lang, C # 8.0 dan .NET Standard 2.0 - Melakukan Hal yang Tidak Didukung .


Kode

C # proyek berikut menargetkan .NET Framework 4.8 dan menggunakan jenis referensi nullable C # 8 mengkompilasi di Visual Studio 16.2.0. Saya membuatnya dengan memilih template .NET Standard Class Library dan kemudian mengeditnya menjadi target .NET Framework sebagai gantinya:

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

Saya kemudian mencoba proyek WinForms .NETFramework 4.5.2, menggunakan .csprojformat warisan , dan menambahkan properti jenis referensi nullable yang sama. Saya mengubah jenis bahasa dalam dialog pengaturan Visual Studio Advanced Build (dinonaktifkan di 16.3) ke latestdan menyimpan proyek. Tentu saja karena titik ini tidak dibangun. Saya membuka file proyek di editor teks dan mengubahnya latestmenjadi previewdalam konfigurasi build PropertyGroup:

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

Saya kemudian mengaktifkan dukungan untuk jenis referensi nullable dengan menambahkan <Nullable>enable</Nullable>ke utama PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Saya memuat ulang proyek, dan itu dibangun.


Detail yang mengerikan

Ketika jawaban ini pertama kali ditulis, C # 8 sedang dalam pratinjau dan banyak pekerjaan detektif yang terlibat. Saya meninggalkan informasi itu di sini untuk anak cucu. Jangan ragu untuk melewatinya jika Anda tidak perlu mengetahui semua detail yang mengerikan.

Bahasa C # secara historis kebanyakan framework netral - yaitu mampu mengkompilasi versi Framework yang lebih lama - meskipun beberapa fitur memerlukan tipe baru atau dukungan CLR.

Sebagian besar penggemar C # telah membaca entri blog Building C # 8.0 oleh Mads Torgersen, yang menjelaskan bahwa fitur tertentu C # 8 memiliki ketergantungan platform:

Aliran, pengindeks, dan rentang asinkron semuanya bergantung pada jenis kerangka kerja baru yang akan menjadi bagian dari .NET Standard 2.1 ... .NET Core 3.0 serta Xamarin, Unity, dan Mono semuanya akan mengimplementasikan .NET Standard 2.1, tetapi .NET Framework 4.8 akan tidak. Ini berarti bahwa tipe yang diperlukan untuk menggunakan fitur ini tidak akan tersedia di .NET Framework 4.8.

Ini terlihat seperti Value Tuple yang diperkenalkan di C # 7. Fitur itu membutuhkan tipe baru - ValueTuplestruktur - yang tidak tersedia di versi NET Framework di bawah 4.7 atau .NET Standard lebih tua dari 2.0. Namun , C # 7 masih dapat digunakan di versi .NET yang lebih lama, baik tanpa tupel nilai atau dengan mereka dengan menginstal paket System.ValueTuple Nuget . Visual Studio memahami ini, dan semua baik-baik saja dengan dunia.

Namun, Mads juga menulis:

Untuk alasan ini, menggunakan C # 8.0 hanya didukung pada platform yang menerapkan .NET Standard 2.1.

... yang jika benar akan mengesampingkan penggunaan C # 8 dengan versi apa pun dari .NET Framework, dan bahkan di pustaka .NET Standard 2.0 yang baru-baru ini kami didorong untuk menggunakan sebagai target dasar untuk kode pustaka. Anda bahkan tidak dapat menggunakannya dengan versi .NET Core lebih lama dari 3.0 karena mereka juga hanya mendukung .NET Standard 2.0.

Investigasi sudah dimulai! -

  • Jon Skeet memiliki versi alpha dari Noda-Time menggunakan C # 8 yang siap untuk menargetkan .NET Standard 2.0 saja. Dia jelas mengharapkan C # 8 / .NET Standard 2.0 untuk mendukung semua kerangka kerja dalam keluarga .NET. (Lihat juga posting blog Jon "Langkah pertama dengan jenis referensi nullable" ).

  • Karyawan Microsoft telah membahas Visual Studio UI untuk C # 8 jenis referensi nullable di GitHub , dan dinyatakan bahwa mereka bermaksud untuk mendukung warisan csproj(format pra-.NET Core SDK csproj). Ini adalah indikasi yang sangat kuat bahwa C # 8 akan dapat digunakan dengan .NET Framework. [Saya menduga mereka akan mundur pada ini sekarang karena dropdown versi bahasa Visual Studio 2019 telah dinonaktifkan dan .NET telah dikaitkan dengan C # 7.3]

  • Tak lama setelah posting blog terkenal, untaian GitHub membahas dukungan lintas platform. Poin penting yang muncul adalah bahwa .NET Standard 2.1 akan menyertakan penanda yang menunjukkan bahwa implementasi default antarmuka didukung - fitur tersebut memerlukan perubahan CLR yang tidak akan pernah tersedia untuk .NET Framework. Inilah bagian penting, dari Immo Landwerth, Manajer Program di tim .NET di Microsoft:

    Kompiler (seperti C #) diharapkan menggunakan keberadaan kolom ini untuk memutuskan apakah akan mengizinkan implementasi antarmuka default atau tidak. Jika kolom tersebut ada, runtime diharapkan dapat memuat & mengeksekusi kode yang dihasilkan.

  • Ini semua menunjuk ke "C # 8.0 hanya didukung pada platform yang menerapkan .NET Standard 2.1" menjadi penyederhanaan yang berlebihan, dan bahwa C # 8 akan mendukung .NET Framework tetapi, karena ada begitu banyak ketidakpastian, saya bertanya di GitHub dan HaloFour menjawab:

    IIRC, satu-satunya fitur yang pasti tidak akan muncul di .NET Framework adalah DIM (metode antarmuka default) karena memerlukan perubahan runtime. Fitur lainnya didorong oleh bentuk kelas yang mungkin tidak pernah ditambahkan ke .NET Framework tetapi dapat di-polyfill melalui kode Anda sendiri atau NuGet (rentang, indeks, iterator asinkron, pembuangan asinkron).

  • Victor Derks berkomentar bahwa " Atribut nullable baru yang diperlukan untuk merancang kasus penggunaan nullable yang lebih kompleks hanya tersedia di System.Runtime.dll yang dikirimkan dengan .NET Core 3.0 dan .NET Standard 2.1 ... [dan] tidak kompatibel dengan .NET Framework 4,8 "

  • Namun, Immo Landwerth berkomentar bahwa "Sebagian besar API kami tidak memerlukan atribut khusus karena jenisnya sepenuhnya generik atau bukan nol" di bawah artikel Coba Jenis Referensi Nullable

  • Ben Hall mengangkat masalah Ketersediaan atribut nullable di luar Core 3.0 di GitHub, dengan catatan berikut dari karyawan Microsoft:

C # 8 akan didukung sepenuhnya pada .net core 3.0 dan .net standard 2.1 saja. Jika Anda mengedit file proyek secara manual untuk menggunakan C # 8 dengan .net core 2.1, Anda berada di wilayah yang tidak didukung. Beberapa fitur C # 8 akan bekerja dengan baik, beberapa fitur C # 8 akan bekerja tidak terlalu baik (misalnya kinerja yang buruk), beberapa fitur C # 8 akan bekerja dengan peretasan tambahan, dan beberapa fitur C # 8 tidak akan berfungsi sama sekali. Sangat rumit untuk dijelaskan. Kami tidak memblokirnya secara aktif sehingga pengguna ahli yang dapat menavigasi dapat melakukannya. Saya tidak akan merekomendasikan campuran & pencocokan yang tidak didukung ini untuk digunakan secara luas.

(Jan Kotas)

Orang-orang seperti Anda yang ingin memahami - dan bekerja di sekitar mereka - bebas menggunakan C # 8. Intinya adalah, tidak semua fitur bahasa akan berfungsi pada target tingkat bawah.

(Immo Landwerth)


Visual Studio 2019

Ada perubahan besar dalam versi RTM dari Visual Studio 2019 versi 16.3 - versi peluncuran untuk C # 8.0: pilihan bahasa dropdown telah dinonaktifkan:

masukkan deskripsi gambar di sini

Alasan Microsoft untuk ini adalah:

Ke depannya, ... setiap versi dari setiap framework akan memiliki satu versi yang didukung dan default, dan kami tidak akan mendukung versi arbitrer. Untuk mencerminkan perubahan ini dalam dukungan, komit ini secara permanen menonaktifkan kotak kombo versi bahasa dan menambahkan tautan ke dokumen yang menjelaskan perubahan tersebut.

Dokumen yang terbuka adalah versi bahasa C # . Ini mencantumkan C # 8.0 sebagai bahasa default untuk HANYA .NET Core 3.x. Ini juga menegaskan bahwa setiap versi dari setiap framework akan, ke depannya, memiliki satu versi yang didukung dan default dan bahwa framework-agnosticism dari bahasa tersebut tidak dapat lagi diandalkan.

Versi bahasa masih dapat dipaksa menjadi 8 untuk proyek .NET Framework dengan mengedit file .csproj.


Caveat emptor

Kombinasi C # 8 / .NET Framework tidak secara resmi didukung oleh Microsoft. Ini, kata mereka, hanya untuk para ahli.

Stephen Kennedy
sumber
3
Ini akan menghilangkan kebingungan apa pun yang berasal dari fakta bahwa kami dapat, jika kami mencoba, menggunakan beberapa fitur C # 8 di luar Standar 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall
2
Atribut nullable baru ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ) yang diperlukan untuk merancang kasus penggunaan nullable yang lebih kompleks hanya tersedia di System.Runtime.dll yang disertakan dengan .NET Core 3.0 dan .NET. Standar NET 2.1. Ini membuat nullable \ C # 8.0 tidak kompatibel dengan, NET Framework 4.8
Victor Derks
3
@BenHall Saya telah menambahkan beberapa kesimpulan dari masalah Anda - terima kasih banyak telah mengangkat masalah ini dan memposting di sini. Silakan mengedit jawaban jika ada yang salah.
Stephen Kennedy
3
Visual Studio 2019 IntelliSense tidak mendukung jenis referensi nullable saat ditentukan melalui <Nullable>enable</Nullable>di csproj. Tampaknya berfungsi saat menggunakan #nullable enablearahan. Lihat juga: github.com/dotnet/project-system/issues/5551
Bouke
3
@odalet Saya tidak akan ragu untuk menargetkan C # 8 dan menggunakan fitur dasar yang tidak memerlukan polyfill (sudah melakukan itu), dan mungkin juga dengan polyfill (tidak membutuhkannya). Namun, nasihat terbaik yang bisa saya berikan adalah: jika ragu, jangan lakukan, setidaknya tidak jika pekerjaan Anda bergantung padanya.
Stephen Kennedy
34

Menurut entri blog ini bahasanya memang terikat pada kerangka:

Ini berarti bahwa tipe yang diperlukan untuk menggunakan fitur ini tidak akan tersedia di .NET Framework 4.8. Demikian juga, implementasi anggota antarmuka default bergantung pada peningkatan runtime baru, dan kami juga tidak akan membuatnya di .NET Runtime 4.8.

Untuk alasan ini, menggunakan C # 8.0 hanya didukung pada platform yang menerapkan .NET Standard 2.1. Kebutuhan untuk menjaga agar runtime tetap stabil telah mencegah kami menerapkan fitur bahasa baru di dalamnya selama lebih dari satu dekade. Dengan sifat side-by-side dan open-source dari runtime modern, kami merasa bahwa kami dapat mengembangkannya lagi secara bertanggung jawab, dan melakukan desain bahasa dengan mempertimbangkan hal itu. Scott menjelaskan dalam Pembaruannya pada .NET Core 3.0 dan .NET Framework 4.8 bahwa .NET Framework akan melihat lebih sedikit inovasi di masa depan, alih-alih berfokus pada stabilitas dan keandalan. Mengingat itu, kami pikir lebih baik melewatkan beberapa fitur bahasa daripada tidak ada yang mendapatkannya.

pengguna1781290
sumber
3
Lebih banyak detail di jawaban lain oleh Stephen Kennedy. Faktanya, cukup mudah untuk membuat subset substansial dari C # 8.0 bekerja saat menargetkan .NET Framework. Tetapi beberapa bagian dari C # 8.0 memerlukan perubahan pada runtime yang tidak akan dibuat oleh Microsoft untuk .NET Framework "lama". Dan mereka tampaknya menghubungkan versi bahasa dan versi .NET lebih dekat.
Jeppe Stig Nielsen
1

C # 8.0 (dan lebih tinggi) hanya didukung di .NET Core 3.x dan versi yang lebih baru. Banyak fitur terbaru memerlukan fitur pustaka dan runtime yang diperkenalkan di versi bahasa .NET Core 3.x: C #

Zdravko Zdravkov
sumber
2
Pernahkah Anda melihat jawaban yang ditandai sebagai benar dari @stephen kennedy di atas?
James Harcourt