摘要:如果您是.NET 开发人员,请做好准备!.NET 10 现已发布,它是一个长期支持 (LTS)版本!这意味着三年的更新、优化和稳定性,使其成为生产环境的可靠选择。无论您开发的是高性能 Web 应用程序、跨平台移动解决方案还是企业软件,此版本都会为整个 .NET
.NET 10 中的新功能:您需要了解的一切
如果您是.NET 开发人员,请做好准备!.NET 10 现已发布,它是一个长期支持 (LTS)版本!这意味着三年的更新、优化和稳定性,使其成为生产环境的可靠选择。无论您开发的是高性能 Web 应用程序、跨平台移动解决方案还是企业软件,此版本都会为整个 .NET 生态系统带来大量改进。
在本文中,我们将深入探讨 .NET 10 的一些新功能,从运行时性能提升到SDK 变更、ASP.NET Core 更新、EF Core 增强功能等等。我们将所有内容分解开来,以便您快速了解哪些更改了,哪些改进了,以及它们如何影响您的代码。
所以,拿起你的键盘,启动你的 IDE,让我们探索.NET 10 中的新功能!
为了撰写这篇文章,我直接从Microsoft 官方文档、GitHub 上的官方 .NET 存储库和 .NET 10 发布视频中收集了信息。
.NET 10 是.NET 9的后继者,将成为长期支持 (LTS) 版本,这意味着它将获得3 年的更新和维护。
如果您想尝试此版本,可以在此处下载:Download .NET 10.0 (Linux, macOS, and Windows) | .NET
.NET 10 运行时已进行优化,新增了一些功能,重点是提高性能并减少代码中的抽象开销。下面,我们将探讨此版本中引入的三个主要增强功能。
.NET 10 的主要目标之一是减少常用语言功能中的抽象开销。为了实现这一目标,JIT(即时编译器)现在可以对数组接口方法进行去虚拟化,从而实现更积极的优化。
在 .NET 10 之前,使用简单循环遍历数组for对于 JIT 来说很容易优化,只需删除边界检查并应用 .NET 9 中引入的循环优化即可:
static int Sum(int array){int sum = 0;for (int i = 0; i但是,使用foreach带有接口的循环(例如IEnumerable引入的虚拟调用)会阻止内联和边界检查消除等优化:
static int Sum(int array){int sum = 0;IEnumerable temp = array;foreach (var num in temp){sum += num;}return sum;}从.NET 10开始,JIT现在可以检测并取消虚拟化这些调用,从而优化循环在数组迭代时的性能。这只是微软在 .NET 中实现不同抽象实现之间性能对等foreach的更广泛计划的第一步。
在.NET 9中,JIT 引入了在堆栈上分配对象的功能(堆栈分配),因为它可以保证对象的寿命不会超过其父方法。这种优化减轻了垃圾收集器 (GC)的负载,并进一步提高了性能。
现在,在.NET 10中,此功能已得到扩展,允许堆栈分配不包含 GC 引用的小型固定大小的值类型数组。
例子
static void Sum{int numbers = { 1, 2, 3 };int sum = 0;for (int i = 0; i在这种情况下,JIT认为这numbers是一个由三个整数组成的固定大小数组,并且不会比Sum方法存活更久,因此它不会在堆上分配它,而是将其放在堆栈上,从而提高内存效率。
这一变化有助于减少引用类型的抽象惩罚,进一步缩小.NET 与低级语言之间的性能差距。
.NET 10在基于 x64 的处理器上引入了对高级矢量扩展 (AVX) 10.2 的支持。AVX 是一套旨在提高矢量运算和并行处理速度的指令集。
该类中提供的新内在函数System.Runtime.Intrinsics.X86.Avx10v2将来可以提高数学计算、图形、人工智能以及任何利用 SIMD(单指令、多数据)处理的应用程序的性能。
重要提示:目前,没有硬件支持 AVX10.2 ,因此默认情况下禁用对这些指令的 JIT 支持,直到兼容硬件可用为止。
.NET 10 库获得了显著的性能改进和新的 API,这些 API 增强了数据处理能力,优化了内存使用,并提高了序列化效率。下面,我们来回顾一下最值得注意的更新。
.NET 10 库获得了显著的性能改进和新的 API
通过指纹查找证书是一种常见的操作,但到目前为止,该X509Certificate2Collection.Find(X509FindType, Object, boolean)方法仅支持使用SHA-1进行搜索。
.NET 10 引入了一种新方法,允许指定要使用的哈希算法,从而提高了搜索证书时的安全性和灵活性。
例子
X509Certificate2Collection coll = store.Certificates.FindBythumbprint(HashAlgorithmName.SHA256, thumbprint);Debug.Assert(coll.Count此增强功能支持使用现代哈希算法(如SHA-256 或 SHA-3-256)对证书进行安全搜索,从而避免与相似哈希长度相关的潜在风险。
PEM (隐私增强邮件)格式广泛用于将证书和密钥存储为文本。以前,该类PemEncoding仅适用于字符串(string)或ReadOnlySpan,对于 ASCII 编码的文件,需要手动转换。
.NET 10 引入了一种新方法,允许直接从 ASCII/UTF-8 文件读取 PEM 编码的数据,从而消除不必要的转换并提高效率。
例子
在.NET 10之前,处理之前需要进行数据转换:
byte FileContents = File.ReadAllBytes(path);char text = Encoding.ASCII.GetString(fileContents);PemFields pemFields = PemEncoding.Find(text);现在,无需转换即可直接读取文件:
byte fileContents = File.ReadAllBytes(path);PemFields pemFields = PemEncoding.FindUtf8(fileContents);这减少了内存消耗并提高了处理 PEM 文件时的性能。
该ISOWeek课程最初设计用于DateTime,但随着的引入DateOnly,需要额外的支持。
.NET 10 包含可直接使用的新ISOWeek重载DateOnly,简化基于周的计算,而无需转换为DateTime。
public static class ISOWeek{public static int GetWeekOfYear(DateOnly date);public static int GetYear(DateOnly date);public static DateOnly ToDateOnly(int year, int week, DayOfWeek dayOfWeek);}这提高了处理不包含时间成分的日期计算的应用程序的精度和可用性。
两个关键领域的性能ZipArchive得到了增强:
1️⃣优化更新模式:之前编辑 ZIP 文件中的文件需要将所有条目加载到内存中,导致资源消耗较高。现在,文件更新更加高效,减少了内存占用。
2️⃣并行提取:由于数据是并行处理的,因此解压缩速度现在更快,并且内部数据结构已经过优化以降低内存消耗。
这些增强功能使得ZipArchive处理大型文件压缩和提取任务时更加高效。
新的重载OrderedDictionary该OrderedDictionary类型已得到改进,具有和的新重载TryAdd,TryGetValue现在返回条目的索引,使数据访问更加高效。
新的重载public class OrderedDictionary{public bool TryAdd(TKey key, TValue value, out int index);public bool TryGetValue(TKey key, out TValue value, out int index);}这使得开发人员可以使用返回的索引进行更快的访问和修改。
示例用法if (!orderedDictionary.TryAdd(key, 1, out int index)){int value = orderedDictionary.GetAt(index).Value;orderedDictionary.SetAt(index, value + 1);}此项改进已应用于JSONObject,使属性更新的性能提高了 10-20%。
使用源生成器进行 JSON 序列化时,循环引用以前默认会导致错误。在 .NET 10 中,现在可以使用来配置序列化行为ReferenceHandler。
例子
[JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)][JsonSerializable(typeof(SelfReference))]internal partial class ContextWithPreserveReference : JsonSerializerContext{}internal class SelfReference{public SelfReference Me { get; set; } = null!;}这可以更好地控制 JSON 序列化中的引用处理,防止错误并提高与复杂数据结构的兼容性。
.NET 10 SDK 在依赖项管理方面进行了重大改进,优化了构建过程并减少了磁盘空间占用。其中一项关键更新是删除了不必要的框架提供的包引用,这有助于增强项目的性能和安全性。
从.NET 10开始,NuGet Audit功能现在可以自动从项目中删除未使用的框架提供的包引用。
✅构建时间更快:构建期间需要恢复和分析的软件包更少。
✅减少磁盘空间占用:删除不必要的依赖项,优化项目大小。
✅安全审核中的误报更少:NuGet Audit 和其他依赖项扫描器等工具将产生更少的错误警报。
启用此功能后,应用程序生成的.deps.json文件将包含更少的包引用,因为.NET 运行时已经提供的包引用会被自动排除。
是的,以下目标框架(TFM)默认启用此功能:
.NET 8.0 和 .NET 10.0.NET Standard 2.0 及更高版本.csproj如果您的项目需要保留所有框架提供的包引用,您可以通过向您的或Directory.Build.props文件添加以下属性来禁用此功能:
false这确保所有包引用仍然包含在.deps.json文件中。
.NET Aspire 9.1引入了多项改进,重点关注用户体验、仪表板自定义和本地开发优化。此版本同时支持.NET 8 (LTS)和.NET 9 (STS),允许开发人员利用任一平台上的最新功能。
此版本的主要目标是“完善、完善、再完善”,解决社区反馈并增强整个平台的整体生活质量改善。
升级到新版本非常简单:
1️⃣在您的应用主机项目文件中更新 SDKMyApp.AppHost.csproj :
2️⃣使用 Visual Studio 的 NuGet 包管理器或通过 VS Code 中的命令行检查 NuGet 包更新。
3️⃣通过运行以下命令更新 .NET Aspire 模板:
dotnet new update如果您的应用程序主机项目文件未引用Aspire.AppHost.Sdk,则您可能仍在使用 .NET Aspire 8。在这种情况下,请参阅 .NET Aspire 9 的升级文档。
改善入职体验.NET Aspire 9.1 通过引入以下内容使入门变得更加容易:
ASP.NET Core 10 对 Blazor、SignalR、Minimal API 和 OpenAPI 3.1 进行了多项改进。本次更新重点关注性能、开发便捷性以及与现代 Web 标准的更好集成。
Blazor 的QuickGrid组件现在包含一个RowClass参数,允许开发人员根据行数据动态地将 CSS 类应用于网格行。
...@code {private string ApplyRowStyle({TYPE} rowItem) =>rowItem.{PROPERTY} == {VALUE} ? "{CSS STYLE CLASS}" : null;}这为根据特定条件设置网格样式提供了更大的灵活性。
以前,Blazor 脚本作为ASP.NET Core 共享框架中的嵌入式资源提供。在 .NET 10 中,这些脚本现在作为静态 Web 资源提供,并具有自动压缩和指纹识别功能,从而提高了加载时间和缓存效率。
路线模板突出显示该[Route]属性现在支持路由模板的语法突出显示,从而更容易在代码编辑器中可视化和管理端点结构。
ASP.NET Core 10 为 SignalR 带来了更新,但具体细节将在未来的预览中提供。
精简 API 持续改进,让您能够更轻松地构建依赖更少的轻量级 Web 服务。后续更新将在发布时进行记录。
ASP.NET Core 10 引入了对 OpenAPI 3.1 的支持,这与2020-12 JSON 模式草案保持一致。此更新使 API 文档更加准确、结构更完善,但也引入了一些重大更改。
builder.Services.AddOpenApi(options =>{options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;});对于构建时 OpenAPI 文档生成,可以使用 MSBuild 选项指定版本:
--openapi-version OpenApi3_0.NET 10 中的一个主要变化是删除了OpenApiAny,现在由 取代JsonNode。
options.AddSchemaTransformer((schema, context, cancellationToken) =>{if (context.JsonTypeInfo.Type == typeof(WeatherForecast)){schema.Example = new OpenApiObject{["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")),["temperatureC"] = new OpenApiInteger(0),["temperatureF"] = new OpenApiInteger(32),["summary"] = new OpenApiString("Bracing"),};}return Task.CompletedTask;});options.AddSchemaTransformer((schema, context, cancellationToken) =>{if (context.JsonTypeInfo.Type == typeof(WeatherForecast)){schema.Example = new JsonObject{["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"),["temperatureC"] = 0,["temperatureF"] = 32,["summary"] = "Bracing",};}return Task.CompletedTask;});这些变化会影响所有 OpenAPI 版本,即使明确指定了 OpenAPI 3.0。
ASP.NET Core 10 现在允许以 YAML 格式提供生成的 OpenAPI 文档,与 JSON 相比,它更易于阅读和维护。
app.MapOpenApi("/openapi/{documentName}.yaml");目前,YAML 支持仅在通过端点提供 OpenAPI 文档时可用。预计在未来版本中将支持构建时 YAML 生成。
该[ProducesResponseType]属性现在支持可选的描述参数,使 API 文档更加清晰、更具信息量。
例子[HttpGet(Name = "GetWeatherForecast")][ProducesResponseType>(StatusCodes.Status200OK, Description = "The weather forecast for the next 5 days.")]public IEnumerable Get此更改通过提供更详细的响应描述改进了 OpenAPI 文档。
ASP.NET Core 10 的未来更新中将详细介绍身份验证和授权方面的其他改进。
以前,C# 9+ 中的顶级语句应用程序需要开发人员手动声明:
public partial class Program这是必要的,以便测试项目可以参考Program该类。
在 .NET 10 中,如果未明确声明,则会自动生成源生成器。如果开发人员手动添加,新的分析器会建议将其删除,以避免冗余。public partial class Program
.NET 10 中的 .NET MAUI 专注于.NET MAUI、.NET for Android、.NET for iOS 和 macOS的质量改进。此更新增强了稳定性、性能和开发人员体验,确保了更加完善和可靠的多平台开发框架。
EF Core 10(EF10)引入了LINQ查询转换的改进和增强ExecuteUpdateAsync,使数据库操作更加灵活、高效。
此版本需要.NET 10 才能编译和运行,并且与旧版 .NET 或 .NET Framework 不兼容。
EF Core 10 继续完善查询转换,优化性能并扩展对常用 LINQ 操作的支持。
关键改进翻译支持DateOnly.ToDateTime(TimeOnly)(#35194,由@mseada94 贡献)。LIMIT优化连续操作的处理(#35384,由@ranma42 贡献)。Count操作性能改进ICollection(#35381,由@ChrisJollyAU 贡献)。这些增强功能有助于确保查询转换为高效的 SQL,同时保持预期的行为。
ExecuteUpdateAsync允许在数据库中进行任意更新操作。以前,这些更新必须使用表达式树来指定,这使得它们难以动态构建。
更新博客的浏览量并有条件地修改其名称需要手动构建表达式树,这使得该过程变得复杂且容易出错:
// Base setters - update the Views onlyExpression, SetPropertyCalls>> setters =s => s.SetProperty(b => b.Views, 8);// Conditionally add SetProperty(b => b.Name, "foo") to setters, based on the value of nameChangedif (nameChanged){var blogParameter = Expression.Parameter(typeof(Blog), "b");setters = Expression.Lambda, SetPropertyCalls>>(Expression.Call(instance: setters.Body,methodName: nameof(SetPropertyCalls.SetProperty),typeArguments: [typeof(string)],arguments:[Expression.Lambda>(Expression.Property(blogParameter, nameof(Blog.Name)), blogParameter),Expression.Constant("foo")]),setters.Parameters);}await context.Blogs.ExecuteUpdateAsync(setters);在 EF Core 10 中,ExecuteUpdateAsync现在支持正则 lambda 表达式,使得动态执行条件更新变得更加简单:
await context.Blogs.ExecuteUpdateAsync(s =>{s.SetProperty(b => b.Views, 8);if (nameChanged){s.SetProperty(b => b.Name, "foo");}});这一改进消除了对复杂表达式树操作的需要,使得更新更易于编写和维护。
C# 14 引入了多项新的语言特性,重点在于提高代码清晰度、减少样板代码并增强性能。主要更新包括未绑定泛型类型的运算符、的隐式转换以及lambda 参数的新选项nameofSpan。
这些功能需要.NET 10并在Visual Studio 2022中受支持。
该field关键字消除了对明确声明的支持字段的需求,从而简化了属性访问器。
以前,要确保无法设置属性,null需要手动定义支持字段:
private string _msg;public string Message{get => _msg;set => _msg = value ?? throw new ArgumentNullException(nameof(value));}迁移到.NET 10可能需要进行调整,因为各个领域(包括.NET Core 库、全球化、加密和 Windows 窗体)都发生了重大变化。
每个更改都属于以下类别之一:
二进制不兼容——现有二进制文件可能无法在新运行时加载或执行,需要重新编译。源不兼容——代码可能需要修改才能使用新的 SDK 或运行时进行编译。行为改变——应用程序在运行时的行为可能有所不同,可能需要代码更新。
总结:.NET 10 将继续存在!
借助.NET 10,我们将获得一个更快、更智能、更高效的平台,以应对现代开发挑战。无论是运行时性能改进、新的 C# 14 功能、ASP.NET Core 增强功能,还是SDK 中更好的工具,此版本都为开发人员带来了改变游戏规则的更新。
作为LTS 版本,.NET 10 是生产应用程序的安全可靠之选,它确保了长期稳定性,同时仍在推动框架的发展。如果您还没有尝试过,不妨先试用一下,看看它如何提升您的工作流程并优化您的应用程序。
来源:steven.wang