【问题标题】:Does C# 8 support the .NET Framework?C# 8 是否支持 .NET 框架?
【发布时间】:2021-09-08 13:12:48
【问题描述】:

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

C# 8 是否支持 .NET Framework?

【问题讨论】:

    标签: c# .net visual-studio .net-standard c#-8.0


    【解决方案1】:

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

    唯一需要的是在 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 标准类库模板创建它,然后将其编辑为以 .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>
    

    然后我通过将&lt;Nullable&gt;enable&lt;/Nullable&gt; 添加到主PropertyGroup 来启用对可空引用类型的支持:

    <PropertyGroup>
       <Nullable>enable</Nullable>
    

    我重新加载了项目,它构建了。


    Visual Studio 2019

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

    Microsoft 的 rationale 是:

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

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

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


    血淋淋的细节

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

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

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

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

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

    不过,Mads 也写道:

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

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

    调查开始了! -

    • Jon Skeet 有一个使用 C# 8 ready to go 的 Noda-Time 的 alpha 版本,它仅针对 .NET Standard 2.0。他显然期望 C# 8/.NET Standard 2.0 支持 .NET 家族中的所有框架。 (另请参阅 Jon 的博文 "First steps with nullable reference types")。

    • Microsoft 员工一直在讨论 C# 8 可空引用类型 on GitHub 的 Visual Studio UI,并表示他们打算支持旧版 csproj(.NET Core SDK 之前的格式 csproj)。这是一个非常强烈的迹象,表明 C# 8 将与 .NET Framework 一起使用。 [我怀疑他们会回溯这件事,因为 Visual Studio 2019 语言版本下拉菜单已被禁用并且 .NET 已与 C# 7.3 绑定]

    • 在著名的博文之后不久,GitHub thread 讨论了跨平台支持。出现的一个重要点是.NET Standard 2.1 will include a marker that denotes that default implementations of interfaces is supported - 该功能需要对.NET Framework 永远不可用的CLR 更改。这是重要的一点,来自 Microsoft .NET 团队的项目经理 Immo Landwerth:

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

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

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

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

    (简·科塔斯)

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

    (伊莫兰德韦斯)


    告诫购买者

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

    【讨论】:

    • 这应该可以消除任何混淆,因为我们可以尝试使用标准 2.1 之外的一些 C# 8 特性 - github.com/dotnet/corefx/issues/40039
    • 设计更复杂的可空用例所需的新可空属性 (docs.microsoft.com/en-us/dotnet/csharp/nullable-attributes) 仅在 .NET Core 3.0 和 .NET Standard 2.1 附带的 System.Runtime.dll 中可用。这使得可为空的\C# 8.0 与 .NET Framework 4.8 不兼容
    • @BenHall 我从您的问题中添加了一些要点 - 非常感谢您提出问题并在此处发布。如果有任何不正确的地方,请随时编辑答案。
    • Visual Studio 2019 IntelliSense 在通过csproj 中的&lt;Nullable&gt;enable&lt;/Nullable&gt; 指定时不支持可为空的引用类型。使用 #nullable enable 指令时它似乎有效。另请参阅:github.com/dotnet/project-system/issues/5551
    • @odalet 对于 C# 8 并使用不需要 polyfill 的基本功能(已经这样做),并且可能也使用 polyfill(不需要它们),我不会有任何疑虑。但是,我能给出的最好建议是:如果有疑问,请不要这样做,至少在您的工作依赖于它的情况下不要这样做。
    【解决方案2】:

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

    这意味着使用这些功能所需的类型在 .NET Framework 4.8 上不可用。同样,默认接口成员实现依赖于新的运行时增强,我们也不会在 .NET Runtime 4.8 中实现。

    因此,仅在实现 .NET Standard 2.1 的平台上支持使用 C# 8.0。十多年来,为了保持运行时稳定,我们一直无法在其中实现新的语言特性。凭借现代运行时的并行和开源性质,我们认为我们可以负责任地再次发展它们,并在考虑到这一点的情况下进行语言设计。 Scott 在他的 .NET Core 3.0 和 .NET Framework 4.8 更新中解释说,.NET Framework 未来的创新将更少,而是专注于稳定性和可靠性。鉴于此,我们认为它错过某些语言功能总比无人获得它们要好。

    【讨论】:

    • 斯蒂芬肯尼迪的另一个答案中的更多细节。事实上,当面向 .NET Framework 时,很容易使 C# 8.0 的大部分子集工作。但是 C# 8.0 的某些部分需要对运行时进行更改,Microsoft 不会为“旧”.NET Framework 进行这些更改。他们似乎将语言版本和 .NET 版本更紧密地联系在一起。
    【解决方案3】:

    C# 8.0(及更高版本)仅在 .NET Core 3.x 及更高版本上受支持 版本。许多最新功能需要库和运行时 .NET Core 3.x 中引入的功能: C# language versioning

    【讨论】:

    • 你看到上面@stephen kennedy 标记为正确的答案了吗?
    猜你喜欢
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 2017-02-11
    相关资源
    最近更新 更多