C#8是否支持.NET Framework?


Answers:


237

是的,C#8可以与.NET Framework以及Visual Studio 2019(如果安装了Nuget包则为 Visual Studio的旧版本)中的.NET Core 3.0 / .NET Standard 2.1之前的其他目标一起使用

语言版本必须8.0在csproj文件中设置为。

无论针对哪个框架,大多数(但不是全部)功能都可用。


起作用的功能

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

可以使用的功能

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

默认界面成员-不起作用

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

有关有效和无效以及可能的polyfill的更多信息,请参见Stuart Lang的文章C#8.0和.NET Standard 2.0-做不受支持的事情


以下针对.NET Framework 4.8并使用C#8可为空的引用类型的C#项目在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; }
    }
}

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

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

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

<PropertyGroup>
   <Nullable>enable</Nullable>

我重新加载了该项目,并进行了构建。


血腥细节

首次编写此答案时,C#8处于预览阶段,涉及许多侦探工作。我将这些信息留在这里供后人参考。如果您不需要了解所有血腥细节,请随时跳过它。

C#语言历来是与框架无关的,即能够编译框架的旧版本,尽管某些功能需要新的类型或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 Framework 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软件包与它们一起使用。Visual Studio理解了这一点,并且一切都很好。

但是,Mads也写道:

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

...如果为真,则将排除在任何版本的.NET Framework中使用C#8,甚至在.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的博客文章“具有可空引用类型的第一步”)。

  • 微软员工一直在GitHub上讨论Visual Studio UI for C#8可为空的引用类型,并且据说他们打算支持旧版csproj(.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#)使用此字段的存在来决定是否允许默认接口实现。如果存在该字段,则运行时应能够加载和执行结果代码。

  • 所有这些都指出“过于简化”了“仅在实现.NET Standard 2.1的平台上支持C#8.0”,而C#8将支持.NET Framework,但是由于存在很大的不确定性,我在GitHub上问,HaloFour回答:

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

  • Victor Derks评论说:“ 设计更复杂的可空使用案例所需的新可空属性仅在与.NET Core 3.0和.NET Standard 2.1一起提供的System.Runtime.dll中可用... [并且]与.NET Framework不兼容4.8“

  • 但是,Immo Landwerth 在“ 尝试可空引用类型 ”一文中评论说:“我们的绝大多数API不需要任何自定义属性,因为类型是完全通用的或非空的”

  • Ben Hall在GitHub 的Core 3.0之外提出了可为空的属性的可用性问题,值得注意的是Microsoft员工的以下评论:

仅在.net core 3.0和.net standard 2.1上完全支持C#8。如果您手动编辑项目文件以将C#8与.net core 2.1一起使用,则您处于不受支持的地区。一些C#8功能将碰巧运行良好,一些C#8功能将不能很好地工作(例如,性能较差),某些C#8功能将受到额外的黑客攻击,而某些C#8功能将根本无法工作。解释很复杂。我们不会主动阻止它,因此可以浏览它的专家用户可以这样做。我不建议广泛使用这种不受支持的混合匹配。

(Jan Kotas)

像您这样愿意理解并在其中解决问题的人可以自由使用C#8。要点是,并非所有语言功能都可以在下层目标上使用。

(Immo Landwerth)


Visual Studio 2019

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

在此处输入图片说明

微软对此的理由是:

展望未来,...每个框架的每个版本都会有一个受支持的默认版本,我们将不支持任意版本。为了反映对支持的更改,此提交将永久禁用语言版本组合框,并向说明更改的文档添加链接。

打开的文档为C#语言版本控制。这列出了C#8.0作为.NET Core 3.x的默认语言。它还确认了每个框架的每个版本都将具有单个受支持的默认版本,并且不再依赖于该语言的框架不可知论。

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


买者自负

Microsoft尚未正式支持C#8 / .NET Framework组合。他们说,这仅适用于专家。


3
这应该清除所有因我们可以(如果我们尝试)使用Standard 2.1之外的C#8功能而引起的混乱-github.com/dotnet/corefx/issues/40039
Ben Hall,

2
设计更复杂的可空使用案例所需的新的可空属性(docs.microsoft.com/zh-cn/dotnet/csharp/nullable-attributes)仅在.NET Core 3.0和.NET附带的System.Runtime.dll中可用。 NET标准2.1。这使得可以为null的\ C#8.0与.NET Framework 4.8不兼容
Victor Derks

3
@BenHall我已为您的问题添加了一些要点-非常感谢您提出问题并在此处发布。如果答案有误,请随时编辑。
斯蒂芬·肯尼迪

3
通过时指定的Visual Studio 2019 IntelliSense不支持可能为空引用类型<Nullable>enable</Nullable>csproj。使用#nullable enable指令时,它似乎起作用。另请参阅:github.com/dotnet/project-system/issues/5551
Bouke

3
@odalet我不会针对C#8并使用不需要polyfills的基本功能(已经做到了),也可能使用了polyfills(不需要它们)。但是,我可以提供的最佳建议是:如果有疑问,请不要这样做,至少在您的工作依赖它的情况下不要这样做。
Stephen Kennedy

34

根据此博客文章,该语言确实与该框架相关:

这意味着使用这些功能所需的类型在.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将来将看到较少的创新,而将重点放在稳定性和可靠性上。鉴于此,我们认为最好是错过某些语言功能,而不是没人获得它们。


3
Stephen Kennedy在另一个答案中有更多详细信息。实际上,在针对.NET Framework时,使C#8.0的实质性子集工作很容易。但是C#8.0的某些部分要求更改运行时,Microsoft不会为“旧” .NET Framework进行更改。他们似乎将语言版本和.NET版本联系在一起。
杰普·斯蒂格·尼尔森

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.