在Visual Studio 2019高级构建设置中,c# 8似乎不适用于.NET框架项目,只有(如下图所示)用于.NET Core 3.0项目:

c# 8支持。net框架吗?


根据这篇博客文章,语言确实是与框架绑定在一起的:

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,如果你安装了NuGet包)。

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

无论目标是哪个框架,大多数(但不是全部)特性都可用。


有效的功能

以下特性仅是语法更改;它们不受框架的影响:

静态局部函数 使用声明 空合并作业 只读的成员 一次性ref structs 位置模式 元组模式 转换表达式 也支持可空引用类型,但是不支持设计更复杂的可空用例所需的新的可空属性。我将在“血淋淋的细节”一节中更详细地介绍这一点。

能够发挥作用的功能

这些需要新的。net框架中没有的类型。它们只能与“polyfill”NuGet包或代码文件一起使用:

异步流- Microsoft.Bcl.AsyncInterfaces 索引和范围

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

默认接口成员不能在. net框架下编译,并且永远无法工作,因为它们需要在CLR中进行运行时更改。. net CLR现在被冻结了,因为。net Core现在是前进的方向。

关于什么可以工作,什么不能工作,以及可能的腻子程序的更多信息,请参阅Stuart Lang的文章,c# 8.0和. net Standard 2.0 -做不支持的事情。


Code

下面的c#项目以。net Framework 4.8为目标,使用c# 8可空引用类型在Visual Studio 16.2.0中编译。我通过选择.NET标准类库模板来创建它,然后编辑它以针对.NET框架:

.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格式,并添加了相同的可空引用类型属性。我在Visual Studio高级构建设置对话框(在16.3中禁用)中将语言类型更改为最新并保存了项目。当然,在这一点上,它没有建立。我在文本编辑器中打开项目文件,并在构建配置PropertyGroup中更改latest为预览:

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

然后,我通过在主属性组中添加< nullable >enable</ nullable >来启用对可空引用类型的支持:

<PropertyGroup>
   <Nullable>enable</Nullable>

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


Visual Studio 2019

c# 8.0的发布版本Visual Studio 2019 version 16.3的RTM版本有一个重大变化:语言选择下拉菜单已被禁用:

微软这样做的理由是:

接下来,……每个框架的每个版本都有一个单独的 支持和默认版本,我们不支持任意版本 版本。为了反映支持方面的变化,这个永久提交 禁用语言版本组合框并添加到文档的链接 解释这种变化。

打开的文档是c#语言版本控制。这里列出了c# 8.0作为. net Core 3的默认语言。x。它也证实了每个框架的每个版本都将有一个受支持的默认版本,并且不再依赖于该语言的框架不可知论。

通过编辑.csproj文件,. net框架项目的语言版本仍然可以强制为8。


血腥的细节

当这个答案第一次被写出来时,c# 8还在预览阶段,涉及到大量的侦探工作。我把这些信息留给子孙后代。如果你不需要知道所有血腥的细节,可以跳过它。

c#语言在历史上主要是框架中立的——即能够编译框架的旧版本——尽管一些特性需要新的类型或CLR支持。

大多数c#爱好者都读过Mads Torgersen的博客文章Building c# 8.0,其中解释了c# 8的某些特性具有平台依赖性:

异步流、索引器和范围都依赖于新的框架类型 这将是。NET标准2.1... .NET核心3.0的一部分 Xamarin, Unity和Mono都将实现。net Standard 2.1,但是。net 而框架4.8则不会。这意味着需要使用的类型 这些特性在。net Framework 4.8中是不可用的。

这看起来有点像c# 7中引入的值元组。该特性需要新的类型——ValueTuple结构——这在4.7以下的NET Framework版本或2.0以上的。NET标准版本中是不可用的。但是,c# 7仍然可以在旧版本的。net中使用,可以不使用值元组,也可以通过安装System来使用值元组。ValueTuple Nuget包。Visual Studio理解了这一点,一切都很好。

然而,麦德斯也写道:

基于这个原因,c# 8.0只在实现。net Standard 2.1的平台上被支持。

...如果这是真的,那么就排除了在任何版本的。net框架中使用c# 8的可能性,甚至在。net标准2.0库中也是如此,直到最近我们才被鼓励使用它作为库代码的基准目标。你甚至不能在3.0以上的。net Core版本中使用它,因为它们也只支持。net Standard 2.0。

调查还在继续!-

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:

编译器(如c#)需要使用该字段来决定是否允许默认接口实现。如果该字段存在,则期望运行时能够加载并执行结果代码。

这一切都指向“c# 8.0只在实现。net标准2.1的平台上被支持”,这是一种过度简化,c# 8将支持。net框架,但是,由于有太多的不确定性,我在GitHub上问了一下,HaloFour回答:

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

Victor Derks commented that "The new nullable attributes required to design the more complex nullable use cases are only available in System.Runtime.dll that ships with .NET Core 3.0 and .NET Standard 2.1... [and] incompatible with .NET Framework 4.8" However, Immo Landwerth commented that "The vast majority of our APIs didn't need any custom attributes as the types are either fully generic or not-null" under the article Try out Nullable Reference Types Ben Hall raised the issue Availability of nullable attributes outside of Core 3.0 on GitHub, with the following comments from Microsoft employees being of note:

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)

像你这样愿意理解他们并为之努力的人 可以自由使用c# 8。关键是,并不是所有的语言特性都可以工作 在底层目标上。

(款项Landwerth)


购者自慎

c# 8/。NET框架组合不是微软官方支持的。他们说,这是专家的专利。