在Visual Studio 2019高级构建设置中,C#8似乎不适用于特定的应用程序.NET框架项目,仅适用于.NET Core 3.0项目:

enter image description here

C#8是否支持.NET框架?

推荐答案

Yes, C# 8 can be used with the .NET Framework和其他比.NET Core 3.0/.Visual Studio 2019中的NET标准2.1(或Visual Studio的旧版本,如果您install a NuGet package岁).

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

无论以哪种框架为目标,大多数(但不是全部)功能都可用.


有效的功能

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

可用于工作的功能

这些需要.NET Framework之外的新类型.它们只能与"PolyFill"NuGet包或代码文件结合使用:

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

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

For more information on what does and doesn't work, and on possible polyfills, see Stuart Lang's article, 100.


代码

下面的C#项目面向.NET Framework 4.8并使用C#8可为空的引用类型,在Visual Studio 16.2.0中编译.我创建它的方法是 Select .NET标准类库模板,然后将其编辑为面向.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格式,并添加了相同的可空引用类型属性.我将Visual Studio高级生成设置对话框(在16.3中禁用)中的语言类型更改为latest,并保存了该项目.当然,这一点并没有建立.我在文本编辑器中打开了项目文件,并在构建配置PropertyGroup中将latest更改为preview:

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

然后,我通过在Main PropertyGroup中添加<Nullable>enable</Nullable>来启用对可为空的引用类型的支持:

<PropertyGroup>
   <Nullable>enable</Nullable>

我重新加载了这个项目,它开始构建.


Visual Studio 2019

Visual Studio 2019版本16.3的RTM版本发生了重大变化,C#8.0的发布版本:语言 Select 下拉菜单已被禁用:

enter image description here

微软在这方面的排名是:

向前看...每个框架的每个版本都有一个

打开的文件是C# language versioning.这将C#8.0列为的默认语言.网络核心3.只有x.它还证实了each version of each framework will, going forward, have a single supported and default version和该语言的框架不可知论不再可靠.

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


血淋淋的细节

100

C#语言历史上一直是mostly framework neutral种——也就是说,能够编译框架的旧版本——尽管有些功能需要新类型或CLR支持.

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

异步流、索引器和范围都依赖于新的框架类型

这看起来有点像C#7中引入的Value Tuples.这一特性需要新的类型——ValueTuple种 struct ——这在4.7或更低版本的NetFramework中是不可用的.NET标准早于2.0.However,C#7仍然可以在旧版本的中使用.NET,或者没有值元组,或者安装System.ValueTuple Nuget package.VisualStudio明白这一点,整个世界都很好.

然而,Mads也写道:

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

...如果这是真的,那么就排除了使用C#8和any版本的.NET框架,甚至在.NET标准2.0库,直到最近我们才被鼓励将其用作库代码的基准目标.你甚至不能用它.NET核心版本早于3.0,因为它们也只支持.NET标准2.0.

调查开始了-

  • Jon Skeet有一个Alpha版本的Noda-Time,使用的是C#8ready to go,它只面向.NET Standard 2.0.他显然希望C#8/.NET Standard 2.0支持.NET系列中的所有框架.(另见乔恩的博客文章"First steps with nullable reference types").

  • 微软员工一直在讨论C#8可空引用类型on GitHub的Visual StudioUI,据称他们打算支持遗留的csproj(.NET之前的核心SDK格式csproj).这是一个非常强烈的迹象,表明C#8将与.NET Framework一起使用.[我怀疑他们将在这方面走回头路,因为Visual Studio 2019语言版本下拉菜单已被禁用,而.NET已与C#7.3Bundle 在一起]

  • 在这篇著名的博文发表后不久,一位GitHub thread人讨论了跨平台支持.出现的一个重要点是.NET Standard 2.1 will include a marker that denotes that default implementations of interfaces is supported——该功能需要一个CLR更改,而该更改将永远不会提供给用户.NET框架.这里是重要的一点,来自于节目经理Immo Landwerth.微软的NET团队:

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

  • 这一切都指向了"C#8.0仅在实现.NET标准2.1的平台上受支持"的过分简化,而C#8将支持.NET框架,但由于存在太多不确定性,I asked on GitHub和Halofur回答:

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

C#8仅在.Net核心3.0和.Net标准2.1上完全受支持. 如果手动编辑项目文件以使用带有.Net Core 2.1的C#8, 您处于不受支持的区域.一些C#8功能将发生在 运行良好,一些C#8特性将不会运行得太好(例如,差 性能),一些C#8特性将与额外的黑客一起工作,而另一些 C#8特性将完全不起作用.解释起来非常复杂.我们没有 积极使用挡路,以便能够浏览它的专家用户能够 那就这么做吧.我不建议使用此不受支持的混搭(&A) 大体上说.

(简·科塔斯)

像你这样愿意理解--并在他们身边工作的人-- 我可以免费使用C#8.关键是,并不是所有的语言特性都能正常工作 在下层目标上.

(伊莫·兰德沃斯)


买主须知

Microsoft不正式支持C#8/.NET Framework组合.他们说,它只对专家开放.

.net相关问答推荐

无法在Designer、VS2022、. NET 8中打开WinForms表单'

为什么$NULL在ForEach-Object{}和Foreach()中的行为不同?

ASP.NET核心最小API必须以正斜杠开头吗?

竖线在 PropertyGroup .csproj 文件中的含义

Msbuild try 构建 msbuild.exe 而不是我的 .csproj 文件

无法实例化类的代理:System.Net.HttpWebRequest.找不到无参数构造函数

什么是提升运算符?

如何使用 C# 关键字作为属性名称?

代理、包装器或外观类之间有什么区别

将屏幕捕获为位图

重新启动(回收)应用程序池

我不了解应用程序域

如何使用 c# 仅获取目录中的文件名?

.Net 中 AOP 的最佳实现是什么?

场与财产.性能优化

无法加载文件或程序集System.ValueTuple

在 C# 中使用 Bitmap 对象查找图像格式

System.Array.CopyTo() 和 System.Array.Clone() 之间的区别

程序员应该使用 SSIS,如果是,为什么?

有没有一种简单的方法来判断 .NET Framework 版本?