作者:Jiachen Jiang
排版:Alan Wang
我们很高兴与您分享 .NET 8 Preview 5 中的所有新功能和改进!此版本是 Preview 4 版本的后续版本。在每月发布的版本中,您将看到更多新功能。.NET 6 和 7 用户可以密切关注此版本,而我们也正在努力使其更容易升级。
您可以下载适用于 Windows、macOS 和 Linux 的 .NET 8 Preview 5。
- 安装程序和二进制文件
- 容器图像
- 发行说明
- 已知的问题
- GitHub 问题跟踪器
您可以查看 Preview 5 版本中 ASP.NET Core 中的新增功能,并了解 .NET 8 中的新增功能和即将推出的新功能。在整个版本中,这些新功能将会不断更新。
Microsoft Build 2023 取得了巨大的成功,这很大程度上归功于像您这样的 .NET 开发者!.NET团队举办的会议吸引了大量参与者,我们在会上讨论了 .NET 8 中一些令人兴奋的功能,并回答了与会者的问题。请加入 Microsoft Build 2023 的 .NET 团队!
现在,让我们来看看.NET 8 中的一些新功能。
SDK:Metrics API 的增强
Preview 5 包含对 Metrics API 的许多改进和更新,涵盖了其他用例。
依赖关系注入 (DI) 友好指标 API
我们推出了 IMeterFactory
接口,该接口可以向 DI 容器注册并用于隔离创建 Meter 对象。
// service is the DI IServiceCollection
// Register the IMeterFactory to the DI container using the default meter factory implementation.
services.AddMetrics();
您现在可以使用下面的代码创建Meter工厂,并使用它来轻松创建新的 Meter 对象。
IMeterFactory meterFactory = serviceProvider.GetRequiredService<IMeterFactory>();
MeterOptions options = new MeterOptions("MeterName")
{
Version = "version",
};
Meter meter = meterFactory.Create(options);
支持创建带有标签的 Meter 和 Instrument
Meter 和 Instrument 也可以使用附加的键值对标签创建。该特性允许发布的特性聚合器根据这些标记区分聚合值。
MeterOptions options = new MeterOptions("name")
{
Version = "version",
// Attach these tags to the created meter
Tags = new TagList() { { "MeterKey1", "MeterValue1" }, { "MeterKey2", "MeterValue2" } }
};
Meter meter = meterFactory.Create(options);
Instrument instrument = meter.CreateCounter<int>("counter", null, null, new TagList() { { "counterKey1", "counterValue1" } });
instrument. Add(1);
SDK:源链接是 .NET SDK 的一部分!
.NET SDK 现在包含源链接,以便在检查源链接的 NuGet 包时增强 IDE 体验。目的是通过将源链接捆绑到 SDK 中来消除对单独 PackageReference 的需要,更多包将默认包含此信息。我们相信这将为开发人员创造更好的 IDE 体验!
源链接是一个与语言和源代码管理无关的系统,用于为二进制文件提供一流的源代码调试体验。该项目的目标是让任何人生成 NuGet 库以便为其用户提供源调试,而无需额外的工作。源链接受 Microsoft 支持,并由 .NET Core 和 Roslyn 等库启用。
Visual Studio 和许多其他编辑器支持在调试时从符号读取源链接信息。编辑器可以为用户下载并显示适当的特定于提交的源代码,例如来自 raw.githubusercontent,它可以在任意 NuGet 依赖项上启用断点和所有其他源调试体验。
源链接的交付实现包括 git、GitHub、GitLab、Azure 存储库和 BitBucket 的提供程序,但 NuGet 上还有更多的提供程序可用。
您可以在学习文档中找到有关源链接的详细信息,并阅读存储库文档中有关可用设置的详细信息。
SDK:新的 .NET 库分析器
分析器类似于内置于 SDK 和交互式开发环境 (IDE) 中的编码伙伴,可在您编写代码时识别问题并提出更正建议。从 .NET 8 Preview 1 开始,我们的团队添加了多个分析器和代码修复器,帮助开发人员验证正确和(或) .NET 库 API 更高效使用。我们很高兴地提到,这些分析器中的大多数都是由我们的社区成员实现的。我们要衷心感谢所有贡献者的辛勤工作和奉献精神。
分析器提案和贡献者 | 描述 | 类别 | 严重性 | 帮助链接 |
---|---|---|---|---|
将常量传递给标记为 [ConstantExpected] 的参数 by @wzchua | 当 ConstantExpected 属性未正确应用于参数时,CA1856 会触发。 当参数用 ConstantExpected 属性注释,但提供的参数不是常量时,CA1857 会触发。 应使用常量以获得最佳性能。 | 性能 | CA1856: Error CA1857: Warning | CA1856, CA1857 |
使用 StartsWith 而不是 IndexOf ==0 by @Youssef1313 | 调用 String.StartsWith 比调用 String.IndexOf 并将结果与零进行比较以确定字符串是否以给定前缀开头更高效、更清晰。 | 性能 | Info | CA1858 |
建议使用具体类型以最大限度地发挥去虚拟化潜力 by @geeknoid | 该规则建议尽可能将特定局部变量、字段、属性、方法参数和方法返回类型的类型从接口或抽象类型升级为具体类型。 使用具体类型可以通过最小化虚拟或接口调度开销并启用内联来生成更高质量的代码。 | 性能 | Info | CA1859 |
优先选择 .Length/Count/IsEmpty 而不是 Any() by @CollinAlpert | 使用 Length、Count 或 IsEmpty 比调用 Enumerable.Any 扩展方法来确定集合类型是否有元素更高效、更清晰。 | 性能 | Info | CA1860 |
将常量数组提取到静态只读字段 @steveberdy | 作为参数传递的常量数组在重复调用时不会重用,这意味着每次都会创建一个新数组。 如果传递的数组未在调用的方法中发生变化,请考虑将其提取到静态只读字段以提高性能。 | 性能 | Info | CA1861 |
不要将 OfType() 与不可能的类型一起使用 by @fowl2 | Enumerable.Cast<T> 和 Enumerable.OfType<T> 需要兼容的类型才能按预期运行。 对于不兼容类型的元素,Enumerable.Cast<T> 将在运行时抛出 InvalidCastException 。Enumerable.OfType<T> 永远不会成功处理不兼容类型的元素,从而导致空序列。 泛型类型不支持扩展和用户定义的转换。 | 可靠性 | Warning | CA2021 |
将参数 null 检查转换为 ArgumentNullException.ThrowIfNull by @stephentoub | 抛出助手比构造新异常实例的 if 块更简单、更高效。 在此分析器中添加了四个分析器:ArgumentNullException 、ArgumentException 、ArgumentOutOfRangeException 和 ObjectDisposeException 抛出帮助器。 | 可维护性 | Info | CA1510, CA1511, CA1512, CA1513 |
我们计划继续向 .NET 8 添加更多分析器,以帮助开发人员编写更好的代码,并期待社区做出更多的贡献。对于社区来说,这是向 .NET 8 SDK 添加一个完整的新功能的绝佳机会。
如果您有兴趣做出贡献,请查看我们已准备好开发并标记为可获取的分析器列表。
SDK:Linux 自包含
Linux 发行版构建(源代码构建)SDK 现在可以构建利用源代码构建运行时包的自包含应用程序。特定于发行版的运行时包将与源构建 SDK 捆绑在一起。在自包含部署期间,将引用此捆绑运行时包,从而为用户启用该功能。请注意,MS 构建的 SDK 没有变化。
感谢我们的 Red Hat 合作伙伴,尤其是@tmds,感谢他们为此功能做出的宝贵贡献。
SDK:自包含不再是默认
从 .NET 6 开始,在发布期间指定运行时会导致以下警告:
> warning NETSDK1179: One of '--self-contained' or '--no-self-contained' options are required when '--runtime' is used.
对于 .NET 8,这种情况最终将消失。 展望未来,对于面向 net8.0
和更高版本目标框架的应用程序,-r/--runtime
将不再意味着 –self-contained
。 如果您想要这种行为,您需要
- 显式添加 CLI 选项,或
- 将
<SelfContained>true</SelfContained>
属性添加到项目文件
面向 .NET 7.0
或更低版本的应用程序不受影响。您可以在我们发布的重大变更通知中了解有关此变更的更多信息。
我们做出这一更改是因为我们相信针对特定平台是将运行时与该平台捆绑在一起的独立决定。 让更多应用程序默认为依赖于框架的部署意味着可以安全地更新运行应用程序的运行时,而无需重建或重新部署。 与自包含部署相比,它还减少了应用程序的大小。
Alpine ASP.NET Docker 合成图像
我们现在提供一个新的 ASP.NET Docker 图像,该图像使用更新的开箱即用 (R2R) 构建变体(称为“composite”)。 合成 R2R 图像是通过将多个 MSIL 程序集编译为单个 R2R 输出二进制文件来构建的。 合成图像有几个优点:减少 JIT 时间、降低启动性能以及减小 R2R 映像大小。
合成图像具有更紧密的版本耦合。这意味着最终的应用程序运行不能使用不同版本的框架(例如 System.Reflection.Metadata 和(或) ASP.NET 二进制文件被嵌入到合成文件中)。这个限制就是我们制作新图像风格的原因。 您的应用程序可能无法按照当前的构建方式使用composite。
这个新的容器图像是新功能。我们决定从基于 Alpine 的新变体开始。通常选择 Alpine 图像是因为它们的尺寸较小,这与该项目的目标是一致的。将来我们可能会扩展对其他图像类型的支持,例如 distroless 图像。
我们在哪里可以获得合成图像?
截至目前,合成图像可在 mcr.microsoft.com/dotnet/nightly/aspnet
存储库中预览。这些标签在官方夜间 Dotnet Docker 页面中以 -composite
后缀列出。
默认情况下,运行时主机在没有RID图的情况下确定RID特定资产
当运行带有 Runtime (RID) 特定资产的应用程序时,主机会决定哪些资产与其运行的平台相关。
这适用于应用程序本身和 AssemblyDependencyResolver 使用的解析逻辑。 默认情况下,在 .NET 8 中,此决定将不再使用 RID 图,而是依赖于基于运行时本身构建方式的已知 RID 列表。
事实证明,RID 图的维护成本高昂、难以理解并且通常很脆弱。此更改是简化 RID 模型的长期目标的一部分。
您可以在重大变更通知中阅读有关此变更的更多信息。
Codegen
动态配置文件引导优化 (PGO) 现在默认启用,这意味着不再需要特殊的配置设置。 我们预计各类应用程序的性能将提高 5% 到 500%(合理预期为 15%),具体取决于应用程序瓶颈的性质。 在我们约 4600 次测试的本地基准测试套件中,23% 的测试提高了 20% 或更多。
- Akka.Net
- Azure Active Directory Gateway
- Microsoft Graph
在过去的版本中,PGO 的客户体验一直都是积极的。但是,如果您是动态 PGO 的新手,我们也期待听到您的体验反馈(无论好坏)。
如有必要,您可以通过以下方式选择退出动态 PGO:
<TieredPGO>false</TieredPGO>
在 .csproj
中或通过运行时配置或环境中的类似设置。
优化 GC 类型的 ThreadStatic 字段访问
标记为 ThreadStaticLocal 的字段访问现在针对原始类型进行了优化。我们还通过 PR#85619 优化了引用类型字段访问。 这些更改在许多基准测试中带来了一些非常好的改进:(windows/arm64 上有 133 个,windows/x64 上有 23 个,16、13、11 个改进)。
Arm64
Preview 5 还带来了一些细微优化:
- 在 PR#85032 中,我们启用了窥视孔优化,以用
stp
替换str
组。 - 在 PR#85657 中,我们启用了窥视孔优化,在 prolog 中用
ldp/stp
替换ldr/str
组。
常规优化
我们的团队发布了许多常规优化,包括:
- PR#85780 中对
movzx
、movsx
和movsxd
等 x64 指令进行了优化,通过消除更多冗余mov
指令,略微改进了代码生成。 - PR#86318 改进了某些冻结对象(非 GC 对象)的常量折叠。 它将生成的代码的大小减少了近 10 倍(例如,从 424 字节减少到 41 字节)。
AVX-512
- PR#85389 启用了 AVX-512 进行区块展开,这增加了以前用于回退到 memcpy/memset 的范围,并将执行时间缩短了一半。
- AVX512F、AVX512BW 和 AVX512CD 启用了各种整数内在函数,PR#85833。
社区 PR(非常感谢 JIT 社区贡献者!)
-
@SingleAccretion 在Preview 5 中贡献了 18 个 PR。其中大部分工作都集中在内部 JIT 清理上,最终目标是大大简化内部表示 (IR),特别是在分配/存储方面。
- PR#85180 标志着这项工作的开始,在未来的预览中,它将导致 JIT 在编译用户函数时速度提高几个百分点。
-
@yesmey 启用了 const 字符串的 StringBuilder.Append 功能,以解锁更多 AVX-512 的使用。 它将 System.Tests.Perf_Enum 基准测试的执行时间提高了 8%,将 StringBuilder 的执行时间提高了 16%,PR#85894。
-
@MichalPetryka 提交了 PR#85398,改进了 JIT 早期推理单定义变量的能力,并提交了 PR#85349,改进了 JIT 的代码生成,以调用不带参数的函数指针。
使用 C# 开发工具包扩展提高 VS Code 的工作效率!
VS Code 中的 C# 开发工具包扩展现在已经可以 在 VS Code 中进行公开预览!我们非常感谢您在 .NET 8 中使用C# 开发工具包 ,并给予反馈。
它旨在提高您在 VS Code 中的 C# 工作效率,C# 开发工具包可帮助你使用解决方案资源管理器管理代码,使用 AI 辅助建议和完成,实现更快地编写代码,并提供在测试资源管理器中运行和调试测试的新功能。使用 Roslyn 支持的语言服务,C# 开发工具包还极大地提高了 C# 语言功能(如代码导航、重构、智能感知等)的性能。
如果您想要开始使用 C# 开发工具包,请查看我们最近的公告博客文章。
社区焦点
DoctorKrolic
我是一名 .NET 后端开发人员,对代码分析应用程序充满热情。喜欢构建强大的后端服务和 C# 生产力工具!在空闲时间,我喜欢为开源项目做出贡献,并跟上最新的行业趋势,以不断提高我的技能和知识。
您可以在 https://aka.ms/net8contributor 提名您已知正在为 .NET 做出贡献的人,我们将会在以后的帖子中介绍他。
总结
.NET 8 Preview 5 包含了令人兴奋的新功能和改进,这些是通过 Microsoft 多元化工程师团队和充满热情的开源社区的辛勤工作和奉献而实现的。我们要感谢迄今为止为 .NET 8 做出贡献的所有人,无论是通过代码贡献、错误报告还是提供反馈。
您的贡献对于制作 .NET 8 预览版发挥了重要的作用,我们期待着继续共同努力,为 .NET 和整个技术社区打造更光明的未来。
好奇接下来会发生什么? 快来亲自看看 .NET 的下一步发展吧!