且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C# 8 是否支持 .NET Framework?

更新时间:2022-10-18 13:53:33

是的,C# 8 可以与 .NET Framework 和其他早于 .NET Core 3.0/.NET Standard 2.1 的目标一起使用在 Visual Studio 2019(或旧版本的 Visual Studio,如果您

微软的理由是:

继续前进,...每个框架的每个版本都会有一个支持和默认版本,我们不会支持任意版本.为了反映这种支持的变化,这个提交永久禁用语言版本组合框并添加指向文档的链接解释变化.

打开的文档是C#语言版本.这仅将 C# 8.0 列为 .NET Core 3.x 的默认语言.它还确认每个框架的每个版本都将有一个单一的受支持和默认版本,并且不能再依赖语言的框架不可知性.

仍然可以通过编辑 .csproj 文件将 .NET Framework 项目的语言版本强制为 8.


血腥细节

第一次编写此答案时,C# 8 处于预览阶段,并且涉及大量侦探工作.我把这些信息留在这里供后代使用.如果您不需要了解所有血腥细节,请随意跳过它.

C# 语言历来是大部分框架中立 - 即能够编译旧版本的框架 - 尽管某些功能需要新类型或 CLR 支持.

大多数 C# 爱好者都会阅读博客条目 Building C# 8.0 作者:Mads Torgersen,其中解释了 C# 8 的某些功能具有平台依赖性:

异步流、索引器和范围都依赖于新的框架类型这将成为 .NET Standard 2.1 ... .NET Core 3.0 以及Xamarin、Unity 和 Mono 都将实现 .NET Standard 2.1,但 .NET框架 4.8 不会.这意味着需要使用的类型这些功能在 .NET Framework 4.8 上将不可用.

这看起来有点像 值元组.该功能需要新类型 - ValueTuple 结构 - 在低于 4.7 的 NET Framework 版本或更早的 .NET Standard 版本中不可用2.0.但是,C# 7 仍然可以在旧版本的 .NET 中使用,无论是没有值元组还是通过安装 System.ValueTuple Nuget 包.Visual Studio 明白这一点,一切都很好.

然而,Mads 也写道:

因此,仅在实现 .NET Standard 2.1 的平台上支持使用 C# 8.0.

...如果是真的,将排除将 C# 8 与任何 版本的 .NET Framework 一起使用,甚至在 .NET Standard 2.0 库中,直到最近我们才被鼓励将其用作库代码的基线目标.您甚至无法将其用于 3.0 之前的 .NET Core 版本,因为它们也仅支持 .NET Standard 2.0.

调查开始了!-

  • Jon Skeet 有一个使用 C# 8 的 Noda-Time alpha 版本 准备就绪,仅针对 .NET Standard 2.0.他显然希望 C# 8/.NET Standard 2.0 能够支持 .NET 系列中的所有框架.(另请参阅 Jon 的博客文章 "第一步具有可为空的引用类型").

  • Microsoft 员工一直在讨论 C# 8 可为空引用类型的 Visual Studio UI 在 GitHub 上,据说他们打算支持旧的 csproj(pre-.NET Core SDK 格式 csproj).这是一个非常有力的迹象,表明 C# 8 将可用于 .NET Framework.[我怀疑既然 Visual Studio 2019 语言版本下拉菜单已被禁用并且 .NET 已与 C# 7.3 绑定,我怀疑他们会回溯]

  • 在著名的博文发布后不久,一个 GitHub 线程讨论了跨平台支持.出现的一个重要点是 .NET Standard 2.1 将包含一个标记,表示接口的默认实现是支持 - 该功能需要 CLR 更改,而 .NET Framework 将永远无法使用该更改.以下是 Microsoft .NET 团队项目经理 Immo Landwerth 的重要内容:

编译器(如 C#)应使用此字段的存在来决定是否允许默认接口实现.如果该字段存在,则预计运行时能够加载 &执行结果代码.

  • 这一切都指向C# 8.0 仅在实现 .NET Standard 2.1 的平台上受支持";过于简单化了,C# 8 将支持 .NET 框架,但由于存在太多不确定性,我 在 GitHub 上询问,HaloFour 回答:

IIRC,唯一绝对不会出现在 .NET Framework 上的功能是 DIM(默认接口方法),因为它需要运行时更改.其他功能由类的形状驱动,这些类可能永远不会添加到 .NET Framework 中,但可以通过您自己的代码或 NuGet(范围、索引、异步迭代器、异步处理)进行填充.

仅 .net core 3.0 和 .net standard 2.1 将完全支持 C# 8.如果您手动编辑项目文件以将 C# 8 与 .net core 2.1 结合使用,您处于不受支持的区域.某些 C# 8 特性会发生在运行良好,某些 C# 8 功能将无法正常运行(例如差性能),一些 C# 8 功能可以使用额外的技巧,还有一些C# 8 功能根本不起作用.解释起来非常复杂.我们不主动阻止它,以便可以浏览它的专家用户可以这样做.我不推荐使用这种不受支持的混搭广泛.

(扬·科塔斯)

像你这样愿意理解——并围绕他们工作——的人可以免费使用 C# 8.重点是,并非所有语言功能都可以使用下层目标.

(伊莫兰沃斯)


警告清空者

Microsoft 不正式支持 C# 8/.NET Framework 组合.他们说,它仅供专家使用.

In Visual Studio 2019 Advanced Build settings, C# 8 does not appear to be available for a .NET Framework project, only (as in the picture below) for a .NET Core 3.0 project:

Does C# 8 support the .NET Framework?

Yes, C# 8 can be used with the .NET Framework and other targets older than .NET Core 3.0/.NET Standard 2.1 in Visual Studio 2019 (or older versions of Visual Studio if you install a NuGet package).

The only thing required is to set language version to 8.0 in the csproj file. You can also do this in Directory.Build.props to apply it to all projects in your solution. Read below for how to do this in Visual Studio 2019, version 16.3 and newer.

Most - but not all - features are available whichever framework is targeted.


Features that work

The following features are syntax changes only; they work regardless of framework:

Features that can be made to work

These require new types which are not in the .NET Framework. They can only be used in conjunction with "polyfill" NuGet packages or code files:

Default interface members - do not, cannot, and never will work

Default interface members won't compile under .NET Framework and will never work because they require runtime changes in the CLR. The .NET CLR is now frozen as .NET Core is now the way forward.

For more information on what does and doesn't work, and on possible polyfills, see Stuart Lang's article, C# 8.0 and .NET Standard 2.0 - Doing Unsupported Things.


Code

The following C# project targetting .NET Framework 4.8 and using C# 8 nullable reference types compiles in Visual Studio 16.2.0. I created it by choosing the .NET Standard Class Library template and then editing it to target .NET Framework instead:

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

I then tried a .NET Framework 4.5.2 WinForms project, using a legacy .csproj format, and added the same nullable reference type property. I changed the language type in the Visual Studio Advanced Build settings dialog (disabled in 16.3) to latest and saved the project. Of course as this point it doesn't build. I opened the project file in a text editor and changed latest to preview in the build configuration PropertyGroup:

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

I then enabled support for nullable reference types by adding <Nullable>enable</Nullable> to the main PropertyGroup:

<PropertyGroup>
   <Nullable>enable</Nullable>

I reloaded the project, and it builds.


Visual Studio 2019

There has been a major change in the RTM version of Visual Studio 2019 version 16.3, the launch version for C# 8.0: the language selection dropdown has been disabled:

Microsoft's rationale for this is:

Moving forward, ... each version of each framework will have a single supported and default version, and we won't support arbitrary versions. To reflect this change in support, this commit permanently disables the language version combo box and adds a link to a document explaining the change.

The document which opens is C# language versioning. This lists C# 8.0 as the default language for .NET Core 3.x ONLY. It also confirms that each version of each framework will, going forward, have a single supported and default version and that the framework-agnosticism of the language can no longer be relied on.

The language version can still be forced to 8 for .NET Framework projects by editing the .csproj file.


The gory details

When this answer was first written, C# 8 was in preview and a lot of detective work was involved. I leave that information here for posterity. Feel free to skip it if you don't need to know all the gory details.

The C# language has historically been mostly framework neutral - i.e. able to compile older versions of the Framework - although some features have required new types or CLR support.

Most C# enthusiasts will have read the blog entry Building C# 8.0 by Mads Torgersen, which explains that certain features of C# 8 have platform dependencies:

Async streams, indexers and ranges all rely on new framework types that will be part of .NET Standard 2.1... .NET Core 3.0 as well as Xamarin, Unity and Mono will all implement .NET Standard 2.1, but .NET Framework 4.8 will not. This means that the types required to use these features won’t be available on .NET Framework 4.8.

This looks a bit like Value Tuples which were introduced in C# 7. That feature required new types - the ValueTuple structures - which were not available in NET Framework versions below 4.7 or .NET Standard older than 2.0. However, C# 7 could still be used in older versions of .NET, either without value tuples or with them by installing the System.ValueTuple Nuget package. Visual Studio understood this, and all was fine with the world.

However, Mads also wrote:

For this reason, using C# 8.0 is only supported on platforms that implement .NET Standard 2.1.

...which if true would have ruled out using C# 8 with any version of the .NET Framework, and indeed even in .NET Standard 2.0 libraries which only recently we were encouraged to use as a baseline target for library code. You wouldn't even be able to use it with .NET Core versions older than 3.0 as they too only support .NET Standard 2.0.

The investigation was on! -

  • Jon Skeet has an alpha version of Noda-Time using C# 8 ready to go which targets .NET Standard 2.0 only. He is clearly expecting C# 8/.NET Standard 2.0 to support all frameworks in the .NET family. (See also Jon's blog post "First steps with nullable reference types").

  • Microsoft employees have been discussing the Visual Studio UI for C# 8 nullable reference types on GitHub, and it is stated that they intend to support the legacy csproj (pre-.NET Core SDK format csproj). This is a very strong indication that C# 8 will be usable with the .NET Framework. [I suspect they will backtrack on this now that the Visual Studio 2019 language version dropdown has been disabled and .NET has been tied to C# 7.3]

  • Shortly after the famous blog post, a GitHub thread discussed cross-platform support. An important point which emerged was that .NET Standard 2.1 will include a marker that denotes that default implementations of interfaces is supported - the feature requires a CLR change that will never be available to the .NET Framework. Here's the important bit, from Immo Landwerth, Program Manager on the .NET team at Microsoft:

Compilers (such as C#) are expected to use the presence of this field to decide whether or not to allow default interface implementations. If the field is present, the runtime is expected to be able to load & execute the resulting code.

  • This all pointed to "C# 8.0 is only supported on platforms that implement .NET Standard 2.1" being an oversimplification, and that C# 8 will support the .NET Framework but, as there is so much uncertainty, I asked on GitHub and HaloFour answered:

IIRC, the only feature that definitely won't appear on .NET Framework is DIM (default interface methods) as that requires runtime changes. The other features are driven by the shape of classes that might never be added to the .NET Framework but can be polyfilled through your own code or NuGet (ranges, indexes, async iterators, async disposal).

C# 8 will be fully supported on .net core 3.0 and .net standard 2.1 only. If you manually edit the project file to use C# 8 with .net core 2.1, you are in unsupported territory. Some C# 8 features will happen to work well, some C# 8 features will work not too well (e.g. poor performance), some C# 8 features will work with extra hacks, and some C# 8 features will not work at all. Very complex to explain. We do not actively block it so the expert users who can navigate through it can do so. I would not recommend this unsupported mix&match to be used broadly.

(Jan Kotas)

People like you who are willing understand -- and work around them -- are free to use C# 8. The point is, not all language features will work on down-level targets.

(Immo Landwerth)


Caveat emptor

The C# 8/.NET Framework combination is not officially supported by Microsoft. It is, they say, for experts only.