C # 8 có hỗ trợ .NET Framework không?


131

Trong cài đặt Bản dựng nâng cao Visual Studio 2019, C # 8 dường như không khả dụng cho dự án .NET Framework, chỉ (như trong hình bên dưới) cho dự án .NET Core 3.0:

nhập mô tả hình ảnh ở đây

C # 8 có hỗ trợ .NET Framework không?

Câu trả lời:


238

Có, C # 8 có thể được sử dụng với .NET Framework và các mục tiêu khác cũ hơn .NET Core 3.0 / .NET Standard 2.1 trong Visual Studio 2019 (hoặc các phiên bản Visual Studio cũ hơn nếu bạn cài đặt gói Nuget ).

Phiên bản ngôn ngữ phải được đặt thành 8.0trong tệp csproj.

Hầu hết - nhưng không phải tất cả - các tính năng đều có sẵn cho bất kỳ khung nào được nhắm mục tiêu.


Các tính năng hoạt động

Các tính năng sau chỉ là thay đổi cú pháp; chúng hoạt động bất kể khuôn khổ:

Các tính năng có thể được thực hiện để hoạt động

Chúng yêu cầu các loại mới không có trong .NET Framework. Chúng chỉ có thể được sử dụng cùng với các gói hoặc tệp mã Nuget "polyfill":

Thành viên giao diện mặc định - không hoạt động

Các thành viên giao diện mặc định sẽ không biên dịch theo .NET Framework và sẽ không bao giờ hoạt động vì chúng yêu cầu thay đổi thời gian chạy trong CLR. .NET CLR hiện đã bị đóng băng vì .NET Core hiện là con đường phía trước.

Để biết thêm thông tin về những gì hoạt động và không hoạt động, và về các polyfills có thể xảy ra, hãy xem bài viết của Stuart Lang, C # 8.0 và .NET Standard 2.0 - Làm những việc không được hỗ trợ .


Dự án C # sau nhắm mục tiêu .NET Framework 4.8 và sử dụng kiểu tham chiếu có thể vô hiệu C # 8 biên dịch trong Visual Studio 16.2.0. Tôi đã tạo nó bằng cách chọn mẫu Thư viện lớp tiêu chuẩn .NET và sau đó chỉnh sửa nó để nhắm mục tiêu .NET Framework thay thế:

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

Sau đó, tôi đã thử một dự án .NET Framework 4.5.2 WinForms, sử dụng .csprojđịnh dạng kế thừa và thêm thuộc tính kiểu tham chiếu nullable giống nhau. Tôi đã thay đổi loại ngôn ngữ trong hộp thoại cài đặt Visual Studio Advanced Build (bị vô hiệu hóa trong 16.3) latestvà lưu dự án. Tất nhiên như điểm này nó không xây dựng. Tôi đã mở tệp dự án trong trình soạn thảo văn bản và thay đổi latestthành previewtrong cấu hình bản dựng PropertyGroup:

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

Sau đó, tôi đã bật hỗ trợ cho các loại tham chiếu có thể vô hiệu bằng cách thêm <Nullable>enable</Nullable>vào chính PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

Tôi tải lại dự án và nó sẽ xây dựng.


Chi tiết đẫm máu

Khi câu trả lời này được viết lần đầu tiên, C # 8 đang được xem trước và rất nhiều công việc trinh thám đã được thực hiện. Tôi để lại thông tin đó ở đây cho hậu thế. Vui lòng bỏ qua nếu bạn không cần biết tất cả các chi tiết đẫm máu.

Ngôn ngữ C # trước đây hầu hết là trung lập với khung - nghĩa là có thể biên dịch các phiên bản cũ hơn của Framework - mặc dù một số tính năng đã yêu cầu các kiểu mới hoặc hỗ trợ CLR.

Hầu hết những người đam mê C # sẽ đọc mục blog Building C # 8.0 của Mads Torgersen, điều này giải thích rằng một số tính năng nhất định của C # 8 có phụ thuộc vào nền tảng:

Các luồng không đồng bộ, trình chỉ mục và phạm vi đều dựa trên các loại khuôn khổ mới sẽ là một phần của .NET Standard 2.1 ... .NET Core 3.0 cũng như Xamarin, Unity và Mono đều sẽ triển khai .NET Standard 2.1, nhưng .NET Framework 4.8 sẽ không phải. Điều này có nghĩa là các loại cần thiết để sử dụng các tính năng này sẽ không khả dụng trên .NET Framework 4.8.

Điều này trông giống như Value Tuples đã được giới thiệu trong C # 7. Tính năng đó yêu cầu các kiểu mới - ValueTuplecấu trúc - không có sẵn trong các phiên bản NET Framework dưới 4.7 hoặc .NET Standard cũ hơn 2.0. Tuy nhiên , C # 7 vẫn có thể được sử dụng trong các phiên bản .NET cũ hơn, hoặc không có bộ giá trị hoặc với chúng bằng cách cài đặt gói System.ValueTuple Nuget . Visual Studio hiểu điều này và tất cả đều ổn với thế giới.

Tuy nhiên, Mads cũng viết:

Vì lý do này, việc sử dụng C # 8.0 chỉ được hỗ trợ trên các nền tảng triển khai .NET Standard 2.1.

... mà nếu đúng thì sẽ loại trừ việc sử dụng C # 8 với bất kỳ phiên bản nào của .NET Framework và thực sự ngay cả trong các thư viện .NET Standard 2.0 mà chỉ gần đây chúng tôi mới được khuyến khích sử dụng làm mục tiêu cơ sở cho mã thư viện. Bạn thậm chí sẽ không thể sử dụng nó với các phiên bản .NET Core cũ hơn 3.0 vì chúng cũng chỉ hỗ trợ .NET Standard 2.0.

Cuộc điều tra đã được tiến hành! -

  • Jon Skeet có phiên bản alpha của Noda-Time sử dụng C # 8 đã sẵn sàng để chỉ nhắm mục tiêu .NET Standard 2.0. Rõ ràng là anh ấy đang mong đợi C # 8 / .NET Standard 2.0 sẽ hỗ trợ tất cả các framework trong họ .NET. (Xem thêm bài đăng trên blog của Jon "Các bước đầu tiên với các loại tham chiếu có thể vô hiệu" ).

  • Các nhân viên của Microsoft đã thảo luận về giao diện người dùng Visual Studio cho các loại tham chiếu có thể vô hiệu hóa C # 8 trên GitHub và có thông báo rằng họ dự định hỗ trợ kế thừa csproj(định dạng pre-.NET Core SDK csproj). Đây là một dấu hiệu rất rõ ràng rằng C # 8 sẽ có thể sử dụng được với .NET Framework. [Tôi nghi ngờ rằng họ sẽ quay lại vấn đề này ngay bây giờ khi trình đơn thả xuống phiên bản ngôn ngữ Visual Studio 2019 đã bị vô hiệu hóa và .NET đã được gắn với C # 7.3]

  • Ngay sau bài đăng trên blog nổi tiếng, một chủ đề GitHub đã thảo luận về hỗ trợ đa nền tảng. Một điểm quan trọng nổi lên là .NET Standard 2.1 sẽ bao gồm một điểm đánh dấu biểu thị rằng các triển khai mặc định của giao diện được hỗ trợ - tính năng yêu cầu thay đổi CLR sẽ không bao giờ có sẵn cho .NET Framework. Đây là một số thông tin quan trọng, từ Immo Landwerth, Giám đốc chương trình của nhóm .NET tại Microsoft:

    Các trình biên dịch (chẳng hạn như C #) được mong đợi sử dụng sự hiện diện của trường này để quyết định có cho phép triển khai giao diện mặc định hay không. Nếu trường hiện diện, thời gian chạy dự kiến ​​sẽ có thể tải và thực thi mã kết quả.

  • Tất cả điều này chỉ ra rằng "C # 8.0 chỉ được hỗ trợ trên các nền tảng triển khai .NET Standard 2.1" là một đơn giản hóa quá mức và C # 8 sẽ hỗ trợ .NET Framework nhưng vì có quá nhiều sự không chắc chắn, tôi đã hỏi trên GitHub và HaloFour đã trả lời:

    IIRC, tính năng duy nhất chắc chắn sẽ không xuất hiện trên .NET Framework là DIM (các phương thức giao diện mặc định) vì yêu cầu thay đổi thời gian chạy. Các tính năng khác được thúc đẩy bởi hình dạng của các lớp mà có thể không bao giờ được thêm vào .NET Framework nhưng có thể được tạo thành thông qua mã của riêng bạn hoặc NuGet (phạm vi, chỉ mục, trình vòng lặp không đồng bộ, xử lý không đồng bộ).

  • Victor Derks nhận xét rằng "Các thuộc tính nullable mới cần thiết để thiết kế các trường hợp sử dụng nullable phức tạp hơn chỉ có sẵn trong System.Runtime.dll đi kèm với .NET Core 3.0 và .NET Standard 2.1 ... [và] không tương thích với .NET Framework 4,8 "

  • Tuy nhiên, Immo Landwerth nhận xét rằng "Phần lớn các API của chúng tôi không cần bất kỳ thuộc tính tùy chỉnh nào vì các loại này hoàn toàn chung chung hoặc không phải null" trong bài viết Hãy thử các loại tham chiếu có thể không có giá trị

  • Ben Hall đã nêu vấn đề Tính khả dụng của các thuộc tính nullable bên ngoài Core 3.0 trên GitHub, với những nhận xét sau từ các nhân viên của Microsoft:

C # 8 sẽ chỉ được hỗ trợ đầy đủ trên .net core 3.0 và .net standard 2.1. Nếu bạn chỉnh sửa thủ công tệp dự án để sử dụng C # 8 với .net core 2.1, bạn đang ở trong lãnh thổ không được hỗ trợ. Một số tính năng C # 8 sẽ hoạt động tốt, một số tính năng C # 8 hoạt động không quá tốt (ví dụ: hiệu suất kém), một số tính năng C # 8 sẽ hoạt động với các bản hack bổ sung và một số tính năng C # 8 sẽ không hoạt động. Rất phức tạp để giải thích. Chúng tôi không chủ động chặn nó nên những người dùng chuyên nghiệp có thể điều hướng qua nó có thể làm như vậy. Tôi không khuyến nghị kết hợp & kết hợp không được hỗ trợ này được sử dụng rộng rãi.

(Jan Kotas)

Những người như bạn, những người sẵn sàng hiểu - và làm việc xung quanh họ - được sử dụng miễn phí C # 8. Vấn đề là, không phải tất cả các tính năng ngôn ngữ sẽ hoạt động trên các mục tiêu cấp thấp.

(Immo Landwerth)


Visual Studio 2019

Đã có một sự thay đổi lớn trong phiên bản RTM của Visual Studio 2019 phiên bản 16.3 - phiên bản khởi chạy cho C # 8.0: menu thả xuống lựa chọn ngôn ngữ đã bị tắt:

nhập mô tả hình ảnh ở đây

sở lý luận của Microsoft cho điều này là:

Trong tương lai, ... mỗi phiên bản của mỗi khung công tác sẽ có một phiên bản được hỗ trợ và mặc định, và chúng tôi sẽ không hỗ trợ các phiên bản tùy ý. Để phản ánh thay đổi này trong hỗ trợ, cam kết này sẽ vô hiệu hóa vĩnh viễn hộp tổ hợp phiên bản ngôn ngữ và thêm liên kết đến tài liệu giải thích thay đổi.

Tài liệu mở ra là phiên bản ngôn ngữ C # . Điều này liệt kê C # 8.0 là ngôn ngữ mặc định CHỈ dành cho .NET Core 3.x. Nó cũng xác nhận rằng mỗi phiên bản của mỗi khung công tác, về sau, sẽ có một phiên bản mặc định và được hỗ trợ duy nhất và không còn có thể dựa vào thuyết bất khả tri của khung công tác nữa.

Phiên bản ngôn ngữ vẫn có thể bị buộc lên 8 cho các dự án .NET Framework bằng cách chỉnh sửa tệp .csproj.


Emptor caveat

Sự kết hợp C # 8 / .NET Framework không được Microsoft hỗ trợ chính thức. Họ nói rằng nó chỉ dành cho các chuyên gia.


3
Điều này sẽ xóa mọi nhầm lẫn bắt nguồn từ thực tế là chúng tôi có thể, nếu chúng tôi cố gắng, sử dụng một số tính năng C # 8 bên ngoài Tiêu chuẩn 2.1 - github.com/dotnet/corefx/issues/40039
Ben Hall

2
Các thuộc tính nullable mới ( docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes ) được yêu cầu để thiết kế các trường hợp sử dụng nullable phức tạp hơn chỉ khả dụng trong System.Runtime.dll đi kèm với .NET Core 3.0 và. Tiêu chuẩn NET 2.1. Điều này làm cho nullable \ C # 8.0 tương thích với, NET Framework 4.8
Victor Derks

3
@BenHall Tôi đã thêm một số điều rút ra từ vấn đề của bạn - cảm ơn bạn rất nhiều vì đã nêu vấn đề và đăng bài ở đây. Vui lòng chỉnh sửa câu trả lời nếu nó không chính xác.
Stephen Kennedy

3
Visual Studio 2019 IntelliSense không hỗ trợ các loại tham chiếu có thể null khi được chỉ định <Nullable>enable</Nullable>trong csproj. Nó dường như hoạt động khi sử dụng các #nullable enablechỉ thị. Xem thêm: github.com/dotnet/project-system/issues/5551
Bouke

3
@odalet Tôi sẽ không ngại nhắm mục tiêu C # 8 và sử dụng các tính năng cơ bản không yêu cầu polyfills (đã làm được điều đó) và có thể với polyfills nữa (không cần chúng). Tuy nhiên, lời khuyên tốt nhất mà tôi có thể là: nếu nghi ngờ, đừng làm điều đó, ít nhất là không nếu công việc của bạn phụ thuộc vào nó.
Stephen Kennedy

34

Theo mục blog này , ngôn ngữ thực sự gắn liền với khuôn khổ:

Điều này có nghĩa là các loại cần thiết để sử dụng các tính năng này sẽ không khả dụng trên .NET Framework 4.8. Tương tự như vậy, các triển khai thành viên giao diện mặc định dựa trên các cải tiến mới về thời gian chạy và chúng tôi cũng sẽ không thực hiện các triển khai đó trong .NET Runtime 4.8.

Vì lý do này, việc sử dụng C # 8.0 chỉ được hỗ trợ trên các nền tảng triển khai .NET Standard 2.1. Nhu cầu giữ thời gian chạy ổn định đã ngăn cản chúng tôi triển khai các tính năng ngôn ngữ mới trong đó trong hơn một thập kỷ. Với tính chất song song và nguồn mở của thời gian chạy hiện đại, chúng tôi cảm thấy rằng chúng tôi có thể phát triển lại chúng một cách có trách nhiệm và thực hiện thiết kế ngôn ngữ với suy nghĩ đó. Scott giải thích trong Bản cập nhật về .NET Core 3.0 và .NET Framework 4.8 rằng .NET Framework sẽ ít đổi mới hơn trong tương lai, thay vào đó tập trung vào tính ổn định và độ tin cậy. Do đó, chúng tôi nghĩ rằng tốt hơn là bỏ lỡ một số tính năng ngôn ngữ hơn là không ai có được chúng.


3
Nhiều chi tiết khác trong câu trả lời khác của Stephen Kennedy. Trên thực tế, nó đủ dễ dàng để làm cho một tập hợp con đáng kể của C # 8.0 hoạt động khi nhắm mục tiêu .NET Framework. Nhưng một số phần của C # 8.0 yêu cầu thay đổi thời gian chạy mà Microsoft sẽ không thực hiện cho .NET Framework "cũ". Và chúng dường như đang gắn phiên bản ngôn ngữ và phiên bản .NET chặt chẽ hơn với nhau.
Jeppe Stig Nielsen

1

C # 8.0 (và cao hơn) chỉ được hỗ trợ trên .NET Core 3.x và các phiên bản mới hơn. Nhiều tính năng mới nhất yêu cầu các tính năng thư viện và thời gian chạy được giới thiệu trong .NET Core 3.x: Phiên bản ngôn ngữ C #


2
Bạn đã thấy câu trả lời được đánh dấu là đúng từ @stephen kennedy ở trên chưa?
James Harcourt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.