.NET 6 中的新增功能

.NET 6 提供 .NET 统一计划的最终部分,该计划在 .NET 5 中启动。 .NET 6 在移动、桌面、IoT 和云应用之间统一了 SDK、基础库和运行时。 除了这方面的统一以外,.NET 6 生态系统还提供了以下功能:

  • 简化开发:轻松入门。 C# 10 中的新语言功能可减少需要编写的代码量。 利用 Web 堆栈和最小 API 的投资,可以轻松地快速编写更小、更快速的微服务。

  • 更佳的性能:.NET 6 是最快的完整堆栈 Web 框架,如果在云中运行,则会降低计算成本。

  • 终极工作效率:.Net 6 和 Visual Studio 2022 提供热重载、新的 git 工具、智能代码编辑、可靠的诊断和测试工具以及更好的团队协作。

.NET 6 将作为长期支持 (LTS) 版本得到三年的支持

预览功能默认为禁用状态。 它们还不支持在生产环境中使用,并且可能会在将来的版本中删除。 新的 RequiresPreviewFeaturesAttribute 用于批注预览 API,如果使用这些预览 API,则相应的分析器会发出警报。

Visual Studio 2022 和 Visual Studio 2022 for Mac(以及更高版本)支持 .NET 6。

本文未涵盖 .NET 6 的所有新功能。 若要查看所有新功能,以及有关本文中列出的功能的详细信息,请参阅宣布发布 .NET 6 博客文章。

性能

.NET 6 包含大量性能改进。 本部分列出了 FileStream按配置优化AOT 编译中的一些改进。 有关详细信息,请参阅 .NET 6 中的性能改进博客文章。

FileStream

已为 .NET 6 重写 System.IO.FileStream 类型,以便在 Windows 上提供更佳的性能和可靠性。 现在 FileStream 绝不会在为 Windows 上的异步 I/O 创建时阻止。 有关详细信息,请参阅 .NET 6 中的文件 IO 改进博客文章。

按配置优化

按配置优化 (PGO) 是指 JIT 编译器根据最常使用的类型和代码路径生成优化后的代码。 .NET 6 引入了动态 PGO。 动态 PGO 与分层编译配合运作,以根据层级 0 中实施的其他检测来进一步优化代码。 动态 PGO 默认情况下处于禁用状态,但可以使用 DOTNET_TieredPGO环境变量来启用它。 有关详细信息,请参阅 JIT 性能改进

Crossgen2

.NET 6 引入了 Crossgen2,它是已被删除的 Crossgen 的后继版本。 Crossgen 和 Crossgen2 是用于提供预先 (AOT) 编译的工具,可改进应用的启动时间。 Crossgen2 是用 C# (而不是 C++)编写的,可执行之前的版本无法实现的分析和优化。 有关详细信息,请参阅有关 Crossgen2 的会话

Arm64 支持

.NET 6 版本支持 macOS Arm64(或“Apple Silicon”)和 Windows Arm64 操作系统,支持本机 Arm64 执行和 x64 模拟。 此外,x64 和 Arm64 .NET 安装程序现在会并行安装。 有关详细信息,请参阅对 macOS 11 和 Windows 11 的 Arm64 和 x64 .NET 支持

热重载

使用热重载功能,可以修改应用源代码,并立即将这些更改应用到正在运行的应用。 此功能的目的是避免在编辑之间重新启动应用程序,从而提高工作效率。 热重载在 Visual Studio 2022 和 dotnet watch 命令行工具中可用。 热重载适用于大多数类型的 .NET 应用以及 C#、Visual Basic 和 C++ 源代码。 有关详细信息,请参阅热重载博客文章

.NET MAUI

.NET 多平台应用 UI ( .NET MAUI) 仍处于预览状态,会在 2022 第一季度推出候选发布版本,并在 2022 的第二季度正式发布 (GA)。 使用 .NET MAUI,可以使用单个代码库生成适用于桌面和移动操作系统的本机客户端应用。 有关详细信息,请参阅博客文章:关于 .NET 多平台应用 UI 的更新

C# 10 和模板

C# 10 包括一些创新,如 global using 指令、文件范围内的命名空间声明和记录结构。 有关详细信息,请参阅 C# 10 中的新增功能

为了配合这些内容,已采用新式 C# .NET SDK 项目模板以使用一些新的语言功能:

  • async Main 方法
  • 顶级语句
  • 目标类型的新表达式
  • 隐式 global using 指令
  • 文件范围的命名空间
  • 可为空引用类型

通过将这些新语言功能添加到项目模板,可从启用的功能开始编写新代码。 但是,在升级到 .NET 6 时,不会影响现有的代码。 有关这些模板更改的详细信息,请参阅博客文章:.NET SDK:新式 C# 项目模板

F# 和 Visual Basic

F# 6 增加了对 F# 语言和 F# 交互窗口的几项改进。 有关详细信息,请参阅 F# 6 中的新增功能

Visual Basic 在 Visual Studio 体验和 Windows 窗体项目启动方面进行了改进。

SDK 工作负载

为了将 .NET SDK 的大小控制到较小,某些组件已放置在新的可选 SDK 工作负载中。 这些组件包括 .NET MAUI 和 Blazor WebAssembly AOT。 如果使用 Visual Studio,它将负责安装所有需要的 SDK 工作负载。 如果使用 .NET CLI,则可以使用新 dotnet workload 命令来管理工作负载:

命令 说明
dotnet workload search 搜索可用的工作负载。
dotnet workload install 安装指定的工作负载。
dotnet workload uninstall 删除指定的工作负载。
dotnet workload update 更新已安装的工作负载。
dotnet workload repair 重新安装所有已安装的工作负载以修复损坏的安装。
dotnet workload list 列出已安装的工作负载。

有关详细信息,请参阅可选的 SDK 工作负载

System.Text.Json APIs

.NET 6 中的 System.Text.Json 已做了许多改进,因此它现在是一个“工业强度”的序列化解决方案。

源生成器

.NET 6 为 System.Text.Json 添加了新的源生成器。 源生成可与 JsonSerializer 配合使用,并且可以通过多种方式进行配置。 它可以提高性能、减少内存使用量并便于程序集剪裁。 有关详细信息,请参阅如何在 System.Text.Json 中选择反射或源生成以及如何在 System.Text.Json 中使用源生成

可写 DOM

添加了新的可写文档对象模型 (DOM),补充预先存在的只读 DOM。 新 API 提供了一种轻型序列化替代方法,针对的是使用普通旧 CLR 对象 (POCO) 类型无法实现的情况。 它还让你能有效地导航到大型 JSON 树的子节,并读取该子节中的数组或反序列化该子节中的 POCO。 添加以下新类型以支持可写 DOM:

有关详细信息,请参阅 JSON DOM 选项

IAsyncEnumerable 序列化

System.Text.Json 现在支持使用 IAsyncEnumerable<T> 实例进行序列化和反序列化。 异步序列化方法在对象图中枚举任何 IAsyncEnumerable<T> 实例,然后将其序列化为 JSON 数组。 添加 JsonSerializer.DeserializeAsyncEnumerable<TValue>(Stream, JsonSerializerOptions, CancellationToken) 新方法以用于反序列化。 有关详细信息,请参阅 序列化

其他新 API

用于验证和设置默认值的新序列化接口:

有关详细信息,请参阅回调

新的属性排序依据属性:

编写“原始”JSON 的新方法:

对流的同步序列化和反序列化:

在序列化期间检测到引用循环时忽略对象的新选项:

有关使用 System.Text.Json 进行序列化和反序列化详细信息,请参阅 .NET 中的 JSON 序列化和反序列化

HTTP/3

.NET 6 包括对 HTTP/3(HTTP 的新版本)的预览支持。 HTTP/3 通过使用名为 QUIC 的新基础连接协议解决了一些现有的功能和性能难题。 QUIC 可以更快速地建立连接,并且连接独立于 IP 地址,使移动客户端能够在 Wi-fi 和移动电话网络之间进行漫游。 有关详细信息,请参阅将 HTTP/3 与 HttpClient 配合使用

ASP.NET Core

ASP.NET Core 包括针对 Blazor WebAssembly 应用和单页应用的最小 API、提前执行 (AOT) 编译方面的改进。 此外,Blazor 组件现在可以从 JavaScript 呈现并集成到现有的基于 JavaScript 的应用。 有关详细信息,请参阅 ASP.NET Core 6 中的新增功能

OpenTelemetry

.NET 6 改进了对 OpenTelemetry 的支持,OpenTelemetry 是工具、API 和 SDK 的集合,有助于分析软件的性能和行为。 System.Diagnostics.Metrics 命名空间中的 API 实现 OpenTelemetry 指标 API 规范。 例如,有四个支持不同指标方案的检测类。 这些检测类包括:

安全性

.NET 6 添加了对两项关键安全缓解措施的预览支持:控制流强制技术 (CET) 以及“写入独占执行”(W^X)。

CET 是一种 Intel 技术,在部分较新的 Intel 和 AMD 处理器中可用。 它将功能添加到硬件,防止某些控制流劫持攻击。 .NET 6为 Windows x64 应用提供了对 CET 的支持,且必须显式启用它。 有关详细信息,请参阅 .NET 6 与 Intel CET 卷影堆栈的兼容性

可通过 .NET 6 在所有操作系统上使用 W^X,但它仅在 Apple Silicon 上默认启用。 W^X 通过禁止内存页同时可写入和可执行来阻止最简单的攻击路径。

IL 剪裁

改进了独立部署的剪裁。 在 .NET 5 中,仅剪裁未使用的程序集。 .NET 6 还添加了对未使用的类型和成员的剪裁。 此外,现在默认启用剪裁警告,会在剪裁可能会删除运行时使用的代码时发出警告。 有关详细信息,请参阅剪裁自包含部署和可执行文件

代码分析

.NET 6 SDK 包括一些新的代码分析器,这些分析器涉及 API 兼容性、平台兼容性、剪裁安全性、在字符串串联和拆分中使用范围、更快的字符串 API 和更快的集合 API。 若要查看新分析器(以及已删除的分析器)的完整列表,请参阅 分析器版本 - .NET 6

自定义平台临界子句

平台兼容性分析器OperatingSystem 类中的 Is<Platform> 方法(例如 OperatingSystem.IsWindows())识别为平台临界子句。 为了让你使用自定义平台临界子句,.NET 6 引入了两个新特性,可用于使用受支持的或不受支持的平台名称对字段、属性或方法进行批注:

Windows 窗体

Application.SetDefaultFont(Font) 是 .NET 6 中的一种新方法,可对整个应用程序设置默认字体。

C# Windows 窗体应用的模板已更新为支持 global using 指令、文件范围内的命名空间以及可为 null 的引用类型。 此外,它们还包括应用程序启动代码,能减少样板代码,并允许 Windows 窗体设计器以首选字体呈现设计图面。 启动代码是对 ApplicationConfiguration.Initialize() 的调用,这是一种源生成的方法,可发出对其他配置方法(如 Application.EnableVisualStyles())的调用。 此外,如果通过 ApplicationDefaultFont MSBuild 属性设置非默认字体,ApplicationConfiguration.Initialize() 会发出对 SetDefaultFont(Font) 的调用。

有关详细信息,请参阅博客文章:Windows 窗体中的新增功能

源生成

源 tarball 包含 .NET SDK 的所有源,现在是 .NET SDK 内部版本的产品。 其他组织(如 Red Hat)可以使用此源 tarball 生成自己的 SDK 版本。

目标框架名字对象

为 .NET 6 添加了其他特定于 OS 的目标框架名字对象 (TFM),例如 net6.0-androidnet6.0-iosnet6.0-macos。 有关详细信息,请参阅 .NET 5 及更高版本的特定于 OS 的 TFM

泛型数学

在预览版中,可以在 .NET 6 中的泛型类型上使用运算符。 .NET 6 引入了许多接口,这些接口利用 C# 10 的新预览功能,即 static abstract 接口成员。 这些接口对应于不同的运算符,例如 IAdditionOperators 表示 + 运算符。 这些接口在 System.Runtime.Experimental NuGet 包中提供。 有关详细信息,请参阅博客文章:泛型数学

.NET 包验证

NuGet 库开发人员可使用新的包验证工具验证包是否一致且格式标准。 可以针对以下内容进行验证:

  • 包版本之间是否存在任何中断性变更。
  • 针对所有特定于运行时的实现,包具有一组相同的公共 API。
  • 目标框架或运行时适用性是否存在任何差距。

有关详细信息,请参阅博客文章:包验证

反射 API

.NET 6 引入了以下新 API,用于检查代码并提供可为 null 的信息:

这些 API 可用于基于反射的工具和序列化程序。

Microsoft.Extensions API

多个扩展命名空间在 .NET 6 中进行了改进,如下表所示。

命名空间 改进
Microsoft.Extensions.DependencyInjection CreateAsyncScope 使你能够安全地对注册 IAsyncDisposable 服务的服务提供商使用 using 语句。
Microsoft.Extensions.Hosting 新的 ConfigureHostOptions 方法简化了应用程序设置。
Microsoft.Extensions.Logging Microsoft.Extensions.Logging 具有用于性能日志记录 API 的新源生成器。 如果将新的 LoggerMessageAttribute 添加到 partial 日志记录方法,则会触发该源生成器。 在编译时,生成器生成 partial 方法的实现,这在运行时通常比现有日志记录解决方案更快。 有关详细信息,请参阅编译时日志记录源生成

新的 LINQ API

.NET 6 中添加了许多 LINQ 方法。 下表中列出的大多数新方法在 System.Linq.Queryable 类型中具有等效方法。

方法 说明
Enumerable.TryGetNonEnumeratedCount<TSource>(IEnumerable<TSource>, Int32) 尝试在不强制枚举的情况下确定序列中的元素数。
Enumerable.Chunk<TSource>(IEnumerable<TSource>, Int32) 将序列的元素拆分为指定大小的区块。
Enumerable.MaxByEnumerable.MinBy 使用键选择器查找最大或最小元素。
Enumerable.DistinctByEnumerable.ExceptByEnumerable.IntersectByEnumerable.UnionBy 使用这些执行特定于集的操作的新方法变体,可以使用键选择器函数指定相等性。
Enumerable.ElementAt<TSource>(IEnumerable<TSource>, Index)Enumerable.ElementAtOrDefault<TSource>(IEnumerable<TSource>, Index) 接受从序列的开始或结束处计数的索引 - 例如 Enumerable.Range(1, 10).ElementAt(^2) 返回 9
Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, TSource)Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.LastOrDefault<TSource>(IEnumerable<TSource>, TSource)Enumerable.LastOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource>, TSource)Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
使用新重载可以指定在序列为空时使用的默认值。
Enumerable.Max<TSource>(IEnumerable<TSource>, IComparer<TSource>)Enumerable.Min<TSource>(IEnumerable<TSource>, IComparer<TSource>) 使用新重载可以指定比较器。
Enumerable.Take<TSource>(IEnumerable<TSource>, Range) 接受 Range 参数以简化序列切片的创建 - 例如,可以使用 source.Take(2..7) 而不是 source.Take(7).Skip(2)
Enumerable.Zip<TFirst,TSecond,TThird>(IEnumerable<TFirst>, IEnumerable<TSecond>, IEnumerable<TThird>) 使用三个指定序列中的元素生成元组序列。

日期、时间和时区改进

.NET 6 中添加了以下两个结构:System.DateOnlySystem.TimeOnly。 它们分别表示 DateTime 的日期部分和时间部分。 DateOnly 适用于生日和周年纪念,而 TimeOnly 适用于日常闹钟和每周营业时间。

现在,可以在安装了时区数据的任何操作上使用 Internet Assigned Numbers Authority (IANA) 或 Windows 时区 ID。 TimeZoneInfo.FindSystemTimeZoneById(String) 方法已更新,当在系统上找不到请求的时区时,能自动将其输入从 Windows 时区转换为 IANA 时区(或者从 IANA 时区转换为 Windows 时区)。 此外,针对仍然需要手动从一个时区格式转换为另一个时区格式的情况,已添加新方法 TryConvertIanaIdToWindowsId(String, String)TryConvertWindowsIdToIanaId

还有其他一些时区改进。 有关详细信息,请参阅 .NET 6 中的日期、时间和时区改进

PriorityQueue 类

新的 PriorityQueue<TElement,TPriority> 类表示同时具有值和优先级的项的集合。 这些项按优先级的升序取消排行 - 即优先级值最低的项首先取消排行。 此类实现最小堆数据结构。

请参阅