C# 8 是否支持 .NET Framework?

Does C# 8 support the .NET Framework?

在 Visual Studio2019 Advanced Build 设置中,C# 8 似乎不适用于 .NET Framework 项目,仅(如下图所示)适用于 .NET Core 3.0 项目:

C# 8 是否支持 .NET Framework?

根据this blog entry,该语言确实与框架相关联:

This means that the types required to use these features won’t be available on .NET Framework 4.8. Likewise, default interface member implementations rely on new runtime enhancements, and we will not make those in the .NET Runtime 4.8 either.

For this reason, using C# 8.0 is only supported on platforms that implement .NET Standard 2.1. The need to keep the runtime stable has prevented us from implementing new language features in it for more than a decade. With the side-by-side and open-source nature of the modern runtimes, we feel that we can responsibly evolve them again, and do language design with that in mind. Scott explained in his Update on .NET Core 3.0 and .NET Framework 4.8 that .NET Framework is going to see less innovation in the future, instead focusing on stability and reliability. Given that, we think it is better for it to miss out on some language features than for nobody to get them.

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

唯一需要做的就是在 csproj 文件中将语言版本设置为 8.0。您也可以在 Directory.Build.props 中执行此操作以将其应用于解决方案中的所有项目。请阅读下文,了解如何在 Visual Studio 2019 版本 16.3 及更高版本中执行此操作。

大多数(但不是全部)功能在目标框架中可用。


有用的功能

以下功能仅为语法更改;无论框架如何,它们都能工作:

可以使用的功能

这些需要 .NET Framework 中没有的新类型。它们只能与“polyfill”NuGet 包或代码文件结合使用:

默认接口成员 - 不能、不能、永远不会工作

Default interface members 不会在 .NET Framework 下编译,也永远不会工作,因为它们需要在 CLR 中进行运行时更改。 .NET CLR 现在被冻结,因为 .NET Core 现在是前进的方向。

有关哪些有效和无效以及可能的 polyfill 的更多信息,请参阅 Stuart Lang 的文章,C# 8.0 and .NET Standard 2.0 - Doing Unsupported Things


代码

以下 C# 项目以 .NET Framework 4.8 为目标并使用 C# 8 可空引用类型在 Visual Studio 16.2.0 中编译。我通过选择 .NET Standard Class 库模板创建它,然后将其编辑为以 .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; }
    }
}

然后我尝试了一个 .NET Framework 4.5.2 WinForms 项目,使用旧版 .csproj 格式,并添加了相同的可为 null 的引用类型 属性。我将 Visual Studio 高级构建设置对话框(在 16.3 中禁用)中的语言类型更改为 latest 并保存了项目。当然,就这一点而言,它不会建立。我在文本编辑器中打开项目文件,并在构建配置 PropertyGroup:

中将 latest 更改为 preview
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <LangVersion>preview</LangVersion>

然后我通过将 <Nullable>enable</Nullable> 添加到主 PropertyGroup:

来启用对可空引用类型的支持
<PropertyGroup>
   <Nullable>enable</Nullable>

我重新加载了项目,然后它就生成了。


Visual Studio 2019

RTM 版本 Visual Studio 2019 版本 16.3,C# 8.0 的启动版本发生了重大变化:已禁用语言选择下拉列表:

Microsoft 的 rationale 是:

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.

打开的文件是C# language versioning。这仅将 C# 8.0 列为 .NET Core 3.x 的默认语言。它还确认 每个框架的每个版本将在未来有一个受支持的默认版本,并且不再依赖该语言的 framework-agnosticism。

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


血淋淋的细节

第一次写这个答案时,C# 8 处于预览阶段,涉及到很多检测工作。为了 post 的真实性,我将这些信息留在此处。如果您不需要了解所有细节,请随意跳过它。

C# 语言历来是 mostly framework neutral - 即能够编译旧版本的框架 - 尽管某些功能需要新类型或 CLR 支持。

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

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.

这看起来有点像 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明白了这一点,世界上一切都很好。

但是,Mads 还写道:

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

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

调查正在进行中! -

  • Jon Skeet 有一个使用 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") 的 Noda-Time 的 alpha 版本。

  • Microsoft 员工一直在讨论 Visual Studio UI for C# 8 可空引用类型 on GitHub,据说他们打算支持遗留 csproj(预 .NET Core SDK 格式 csproj)。这是一个非常强烈的迹象,表明 C# 8 将可用于 .NET Framework。 [我怀疑他们会在 Visual Studio 2019 语言版本下拉列表中回溯 ha已被禁用,.NET 已绑定到 C# 7.3]

  • 在著名博客 post 之后不久,一个 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 - 该功能需要对 .NET Framework 永远不可用的 CLR 更改。以下是来自 Microsoft .NET 团队项目经理 Immo Landwerth 的重要信息:

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.

  • 这一切都表明“C# 8.0 仅在实现 .NET Standard 2.1 的平台上受支持”是一种过于简单化的说法,C# 8 将支持 .NET Framework,但由于存在太多不确定性,我 asked on GitHub 和 HaloFour 回答:

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.

(简·科塔斯)

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.

(伊莫·兰德沃斯)


买者自负

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

C# 8.0 (and higher) is supported only on .NET Core 3.x and newer versions. Many of the newest features require library and runtime features introduced in .NET Core 3.x: C# language versioning