我们很高兴地发布了.NET 6预览版5。 我们现在处于.NET 6版本的后半部分,并开始看到重要的功能正在形成。一个很好的例子是.NET SDK Workloads,它是我们.NET统一愿景的基础,能够支持更多的应用类型。就像其他功能一样,它正在形成一个引人注目的端到端用户体验。
你可以下载Linux、macOS和Windows的.NET 6 Preview 5:
请参阅ASP.NET Core、EF Core和.NET MAUI的帖子,了解更多关于网络、数据访问和跨平台UI场景的新内容。
Visual Studio 2022 Preview 1也在今天发布,.NET 6 Preview 5也包含在该版本中。.NET 6也已通过Visual Studio 16.11和Visual Studio for Mac 8.9的测试。如果你想用Visual Studio尝试.NET 6,我们建议你使用这些构建。
请查看新的对话帖子,了解工程师之间对最新的.NET功能的深入讨论。
.NET SDK:可选的工作负载改进
SDK工作负载是一项新的.NET SDK功能,它使我们能够在不增加SDK规模的情况下增加对新应用类型的支持--如移动和WebAssembly。
工作负载功能已经更新,包括list
和update
动词。这些新功能提供了一个预期的最终体验的感觉。你将能够通过几个简单的命令快速建立你喜欢的环境,并随着时间的推移保持它的最新状态:
dotnet workload list
将告诉你已经安装了哪些工作负载。dotnet workload update
将把所有安装的工作负载更新到最新的可用版本。
update
动词查询nuget.org
更新工作负载清单,更新本地清单,下载已安装工作负载的新版本,然后删除工作负载的所有旧版本。这与apt update
和apt upgrade -y
(在基于 Debian 的 Linux 发行版上使用)相类似。
dotnet workload
命令是在给定的SDK的背景下操作的。假设你同时安装了.NET 6和.NET 7。如果你同时使用两者,工作负载命令将提供不同的结果,因为工作负载将是不同的(至少是相同工作负载的不同版本)。
正如你所看到的,工作负载功能本质上是一个.NET SDK的包管理器。工作负载是在.NET 6预览版4中首次推出的。
.NET SDK:NuGet软件包验证
包验证工具将使NuGet库的开发者能够验证他们的包是否一致和格式良好。
这包括:
- 验证各版本之间是否有破坏性的变化。
- 验证软件包对所有运行时的特定实现具有相同的公共API集。
- 确定任何目标框架或运行时间的适用性差距。
这个工具可以通过Microsoft.DotNet.PackageValidation获得。
关于这个工具的帖子很快就会出现。
.NET SDK:更多的Roslyn分析器
在.NET 5中,我们在.NET SDK中提供了大约250个分析器。其中许多已经存在,但作为NuGet包被带外发货。我们正在为.NET 6增加更多的分析器。
默认情况下,大多数新的分析器是在信息级别启用的。你可以通过这样配置分析模式,在警告级别启用这些分析器:<AnalysisMode>AllEnabledByDefault</AnalysisMode>
。
我们为.NET 6发布了我们想要的一组分析器(加上一些额外的),然后将它们中的大部分供人取用。
.NET SDK:为平台兼容性分析器启用自定义的防护措施
CA1416平台兼容性分析器已经使用OperatingSystem/RuntimeInformation中的方法识别了平台防护,例如OperatingSystem.IsWindows
和OperatingSystem.IsWindowsVersionAtLeast
。然而,分析器并没有识别任何其他的防护可能性,例如在字段或属性中缓存的平台检查结果,或者在辅助方法中定义复杂的平台检查逻辑。
为了允许自定义防护的可能性,我们添加了新的属性 SupportedOSPlatformGuard
和UnsupportedOSPlatformGuard
,用于用相应的平台名称和/或版本来注释自定义防护成员。这种注释被平台兼容性分析器的流程分析逻辑所识别和尊重。
使用方法
[UnsupportedOSPlatformGuard("browser")] // The platform guard attribute
#if TARGET_BROWSER
internal bool IsSupported => false;
#else
internal bool IsSupported => true;
#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
{
ApiNotSupportedOnBrowser(); // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'
if (IsSupported)
{
ApiNotSupportedOnBrowser(); // Not warn
}
}
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
{
ApiOnlyWorkOnWindowsLinux(); // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.
if (_isWindowOrLinux)
{
ApiOnlyWorkOnWindowsLinux(); // Not warn
}
}
}
Windows窗体:默认字体
现在你可以用Application.SetDefaultFont
为一个应用程序设置默认字体。你使用的模式类似于设置高dpi或视觉样式:
class Program
{
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
+ Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8f));
Application.Run(new Form1());
}
}
下面是设置默认字体后的两个例子(用不同的字体)。
Microsoft Sans Serif,8pt:
Chiller,12pt:
默认字体在.NET Core 3.0中进行了更新。然而,这一变化为一些将.NET框架应用程序迁移到.NET核心的用户带来了重大障碍。这个新变化使得为应用程序选择所需的字体变得简单明了,并消除了迁移的障碍。
库:放弃对旧框架的支持
从软件包中删除一个框架是一个断源的变化。同时,继续为我们曾经交付的所有框架进行构建会增加软件包的复杂性和大小。在过去,我们通过收获来解决这个问题,这基本上意味着:
- 我们只为当前的框架进行构建
- 在构建过程中,我们下载软件包的早期版本,并为我们不再构建的早期框架收获二进制文件。
虽然这意味着你可以随时更新而不用担心我们放弃一个框架,但也意味着如果你使用收获的二进制文件,你将永远不会得到任何错误修复或新功能。换句话说,收获的资产不能被服务,这一点现在是隐藏的,因为从你的角度来看,你能够不断地将包更新到更高的版本,即使你消费的是我们不再更新的旧二进制文件。
从.NET 6预览版开始,我们计划不再进行任何形式的收割,以确保我们运送的所有资产都能得到服务。这意味着我们将放弃对任何早于这些的框架的支持:
- .NET框架4.6.1
- .NET核心3.1
- .NET标准2.0
如果你目前引用了一个来自早期框架的受影响的软件包,你将不再能够将引用的软件包更新到更高版本。你的选择是,要么将你的项目重新定位到一个较新的框架版本,要么不更新被引用的包(这通常不是一个巨大的损失,因为你已经在使用一个冻结的二进制文件)。
更多细节,包括受影响软件包的完整列表,请参见dotnet/announcement。抛弃旧的框架版本。
库:Microsoft.Extensions
我们在这个版本中一直在改进Microsoft.Extensions
APIs。在Preview 5中,我们专注于托管和依赖性注入。在预览版4中,我们增加了一个用于记录的编译时源生成器。
归功于Martin Björkström](github.com/bjorkstromm… #51840(AsyncServiceScope)](github.com/dotnet/runt…
托管:ConfigureHostOptions API
我们在IHostBuilder上增加了一个新的ConfigureHostOptions API,使应用程序的设置更加简单(例如配置关机超时):
using HostBuilder host = new()
.ConfigureHostOptions(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
})
.Build();
host.Run();
在Preview 5之前,配置主机选项是比较复杂的:
using HostBuilder host = new()
.ConfigureServices(services =>
{
services.Configure<HostOptions>(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
});
})
.Build();
host.Run();
依赖性注入 - CreateAsyncScope APIs
你可能已经注意到,当处置服务提供者恰好注册了一个IAsyncDisposable服务时,会抛出一个InvalidOperationException
。
新的CreateAsyncScope
API提供了一个直接的解决方案,你可以在下面的例子中看到:
await using (var scope = provider.CreateAsyncScope())
{
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}
下面的例子展示了现有的问题案例,然后是之前建议的解决方法:
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
await using var provider = new ServiceCollection()
.AddScoped<Foo>()
.BuildServiceProvider();
// This using can throw InvalidOperationException
using (var scope = provider.CreateScope())
{
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}
class Foo : IAsyncDisposable
{
public ValueTask DisposeAsync() => default;
}
你可以通过将返回的范围投给IAsyncDisposable
来解决这个异常。
var scope = provider.CreateScope();
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
await ((IAsyncDisposable)scope).DisposeAsync();
CreateAsyncScope
解决了这个问题,使你可以安全地使用 using
语句。
图书馆: JsonSerializer
源码生成
几乎所有的.NET序列化程序的骨干都是反射。反射在某些情况下是一种很好的能力,但不能作为高性能云原生应用的基础(通常是(去)序列化和处理大量的JSON文档)。反射对于启动、内存使用和汇编修剪都是一个问题。
运行时反射的替代品是编译时源码生成器。源码生成器生成C#源码文件,可以作为库或应用程序构建的一部分进行编译。在编译时生成源代码可以为.NET应用程序提供许多好处,包括提高性能。
在.NET 6中,我们包括一个新的源码生成器,作为System.Text.Json
。JSON源码生成器与JsonSerializer
,并可以以多种方式进行配置。你可以决定是否使用新的源码生成器。它可以提供以下好处:
- 减少启动时间
- 提高序列化的吞吐量
- 减少私有内存的使用
- 移除运行时使用的
System.Reflection
,并且System.Reflection.Emit
- 允许修剪兼容的JSON序列化
例如,在使用Reflection.Emit
(去)序列化过程中,不是在运行时动态生成方法来获取和设置类的属性(这需要使用私有内存并有启动成本),源码生成器可以生成更简单有效的代码,直接向/从属性分配或检索一个值,这是快得惊人。
你可以通过使用System.Text.Json NuGet包的最新预览版来尝试源代码生成器。我们正在研究在SDK中加入源码生成器的建议。
生成优化的序列化逻辑
默认情况下,JSON源码生成器为给定的可序列化类型发出序列化逻辑。这比使用现有的JsonSerializer
方法,通过生成直接使用Utf8JsonWriter
的源代码提供更高的性能。简而言之,源码生成器提供了一种方法,在编译时给你一个不同的实现,以便使运行时的体验更好。
放大来看,JsonSerializer
是一个强大的工具,它有许多功能(甚至更多的功能即将到来!),可以改善.NET类型从/到JSON格式的(去)序列化。它的速度很快,但当一个序列化程序只需要一个子集的功能时,会有一些性能开销。展望未来,我们将一起更新JsonSerializer
和新的源码生成器。
给定一个简单的类型:
namespace Test
{
internal class JsonMessage
{
public string Message { get; set; }
}
}
源码生成器可以被配置成为实例JsonMessage
类型的实例生成序列化逻辑。注意,JsonContext
这个类名是任意的。你可以为生成的源使用你想要的任何类名。
using System.Text.Json.Serialization;
namespace Test
{
[JsonSerializable(typeof(JsonMessage)]
internal partial class JsonContext : JsonSerializerContext
{
}
}
我们已经定义了一组JsonSerializer
的特性,这些特性支持提供最佳序列化吞吐量的源生成模式,通过JsonSerializerOptionsAttribute
。这些特性可以提前指定给源码生成器,以避免运行时的额外检查。如果不使用该属性,那么在运行时将假定默认的JsonSerializationOptions
。
作为构建的一部分,源码生成器用下面的形状增强JsonContext
部分类:
internal partial class JsonContext : JsonSerializerContext
{
public static JsonContext Default { get; }
public JsonTypeInfo<JsonMessage> JsonMessage { get; }
public JsonContext(JsonSerializerOptions options) { }
public override JsonTypeInfo GetTypeInfo(Type type) => ...;
}
采用这种模式的序列化器调用可能看起来像下面的例子。这个例子提供了可能的最佳性能:
using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);
JsonContext.Default.JsonMessage.Serialize(writer, new JsonMessage { "Hello, world!" });
writer.Flush();
// Writer contains:
// {"Message":"Hello, world!"}
另外,你可以继续使用JsonSerializer
,而把生成的代码的一个实例传递给它,用JsonContext.Default.JsonMessage
。
JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);
下面是一个类似的用法,使用不同的重载:
JsonSerializer.Serialize(jsonMessage, typeof(JsonMessage), JsonContext.Default);
这两个重载的区别在于,第一个重载使用的是类型化的元数据实现--JsonTypeInfo<T>
,而第二个重载使用的是一个更通用的非类型化实现,它进行类型测试以确定上下文实例中是否存在一个类型化的实现。因此,它有点慢(由于类型测试的原因)。如果对于一个给定的类型没有源码生成的实现,那么序列化器会抛出一个NotSupportedException
。它不会退回到一个基于反射的实现(作为一个明确的设计选择)。
最快和最优化的源码生成模式--基于Utf8JsonWriter
,目前只适用于序列化。类似的反序列化支持--基于Utf8JsonReader
--在未来可能会被提供,这取决于你的反馈。
然而,源码生成器也会发出类型元数据的初始化逻辑,这也有利于反序列化。要使用预先生成的类型元数据对JsonMessage
的实例进行反序列化,你可以做以下工作:
JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);
与上面的序列化类似,你也可以写:
JsonSerializer.Deserialize(json, typeof(JsonMessage), JsonContext.Default);
补充说明
- 多个类型可以通过
[JsonSerializable]
在一个派生的、部分的JsonSerializerContext
实例上包含在源生成中,而不是只有一个。 - 源生成器还支持对象上的嵌套对象和集合成员,而不仅仅是原始类型。
库:WebSocket压缩
压缩对于在网络上传输的任何数据都很重要。WebSockets现在可以实现压缩。我们使用了permessage-deflate
extension for WebSockets的实现,RFC 7692。它允许使用DEFLATE算法压缩WebSockets消息有效载荷。
这项功能是GitHub上用户对Networking的最高要求之一。你可以通过API审查1和API审查2了解我们提供该API的历程。
我们意识到,将压缩和加密一起使用可能会导致攻击,如CRIME和BREACH。这意味着一个秘密不能与用户生成的数据一起在一个单一的压缩环境中发送,否则该秘密可能被提取。为了让用户注意到这些影响,并帮助他们权衡风险,我们将我们的API更名为DangerousDeflateOptions
。我们还增加了关闭特定信息的压缩功能,所以如果用户想发送一个秘密,他们可以在没有压缩的情况下安全地进行。
在禁用压缩时,将WebSocket的内存占用减少了约27%。
从客户端启用压缩功能很容易,见下面的例子。然而,请记住,服务器可以协商设置,例如要求更小的窗口,或完全拒绝压缩:
var cws = new ClientWebSocket();
cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions()
{
ClientMaxWindowBits = 10,
ServerMaxWindowBits = 10
};
最近还增加了对ASP.NET Core的WebSocket压缩支持。它将被包含在即将到来的预览中。
库:支持SOCKS代理
SOCKS是一个代理服务器实现,可以处理任何TCP或UDP流量,使其成为一个非常通用的系统。它是一个长期存在的社区要求,已经被添加到.NET 6中。
这一变化增加了对Socks4、Socks4a和Socks5的支持。 例如,它可以通过SSH测试外部连接或连接到Tor网络。
WebProxy
类现在接受socks
方案,你可以在下面的例子中看到。
var handler = new HttpClientHandler
{
Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);
库:对OpenTelemetry指标的支持
在过去的几个.NET版本中,我们一直在增加对OpenTelemetry的支持,这也是我们关注可观察性的一部分。在.NET 6中,我们将增加对OpenTelemetry Metrics API的支持。通过增加对OpenTelemetry的支持,你的应用程序可以与其他OpenTelemetry系统进行无缝互操作。
System.Diagnostics.Metrics是OpenTelemetry Metrics API规范的.NET实现。Metrics APIs明确地设计用于处理原始测量,通常是为了有效地、同时地产生这些测量的连续摘要。
这些API包括Meter
类,可用于创建仪器对象(如计数器)。该API暴露了四个仪器类。Counter
,Histogram
,ObservableCounter
, 和ObservableGauge
,以支持不同的度量方案。另外,API暴露了MeterListener
类,以允许监听仪器的记录测量,用于聚合和分组的目的。
OpenTelemetry .NET的实现将被扩展以使用这些新的API,这些API增加了对度量观测方案的支持。
库测量记录实例
Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");
Counter<int> counter = meter.CreateCounter<int>("Requests");
counter.Add(1);
counter.Add(1, KeyValuePair.Create<string, object>("request", "read"));
监听实例
MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meterListener) =>
{
if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb")
{
meterListener.EnableMeasurementEvents(instrument, null);
}
};
listener.SetMeasurementEventCallback<int>((instrument, measurement, tags, state) =>
{
Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.Start();
库:BigInteger性能
对十进制和十六进制字符串的BigIntegers解析已经得到改进。如下图所示,我们看到了高达89%的改进。
库:Vector<T>
现在支持nint
和nuint
Vector<T>
现在支持C# 9中添加的 nint
和 原始类型nuint
。例如,这一变化应该会使使用带有指针或与平台有关的长度的SIMD指令变得更加简单。
库:对OpenSSL 3的支持
.NET密码学API支持使用OpenSSL 3作为Linux上首选的本地密码学提供者。如果OpenSSL 3可用,.NET 6将使用它。否则,它将使用OpenSSL 1.x。
库:增加对ChaCha20/Poly1305加密算法的支持
ChaCha20Poly1305
类已被添加到System.Security.Cryptography
。为了使用ChaCha20/Poly1305算法,它必须被底层操作系统所支持。静态IsSupported
属性可用于确定该算法在给定的环境中是否被支持。
互操作:Objective-C互操作性支持
团队一直在增加对Objective-C的支持,目的是为.NET提供一个单一的Objective-C互操作实现。到目前为止,Objective-C互操作系统是围绕Mono嵌入API建立的,但我们认为这不是跨运行时共享的正确方法。因此,我们创建了一个新的.NET API,它将实现一个单一的Objective-C互操作体验,最终将在两个运行系统上工作。
这个用于Objective-C互操作的新API在两个运行系统中都带来了对以下内容的即时支持 NSAutoreleasePool
,这使得对Cocoa的引用计数内存管理系统的支持成为可能。你现在可以配置你是否希望每个被管理的线程都有一个隐含的NSAutoreleasePool
。这使得Cocoa对象的释放以每线程为基础。
诊断(EventPipe/DiagnosticsServer) - MonoVM
自.NET 6开始,许多诊断功能已经被添加到MonoVM中。这使得管理的EventSource/EventListener、EventPipe和DiagnosticsServer等功能得以实现。它使得在移动设备(iOS/Android)和桌面上运行的应用程序能够使用诊断工具,如dotnet-trace
,dotnet-counters
,dotnet-stacks
。
这些新功能开启了在PrefView/SpeedScope/Chromium、dotnet-trace等工具中分析MonoVM生成的nettrace文件的能力,或者使用TraceEvent等库编写自定义解析器。
我们将继续加入更多的功能,主要集中在SDK的集成和将更多的本地运行时事件(Microsoft-Windows-DotNETRuntime
)调整到MonoVM中,使nettrace文件中有更多的事件。
以下功能现在已经到位了:
- 在MonoVM和CoreCLR之间共享本地EventPipe/DiagnosticsServer库。
- 在DiagnosticsServer中添加TCP/IP支持,并利用该配置构建MonoVM的iOS/Android运行时包。为了支持移动平台,需要这样做。
- BCL EventSources在MonoVM上运行,将事件发射到EventPipe。
- BCL运行时的计数器由
System.Diagnostics.Tracing.RuntimeEventSource
,并在MonoVM上布线,可由dotnet-counters
等工具消耗。 - 自定义事件源在MonoVM上运行,向EventPipe发射自定义事件,可从
dotnet-trace
等工具中消耗。 - 自定义事件计数器在MonoVM上运行,向EventPipe中发射自定义计数器事件,可从
dotnet-counters
等工具中消耗。 - 样品分析器在MonoVM上实现,将事件发射到EventPipe中。使用
dotnet-trace
,开启了在MonoVM上进行CPU剖析的能力。 - 实施
dotnet-dsrouter
诊断工具,可以使用现有的诊断工具,如dotnet-trace
,dotnet-counters
,dotnet-stack
,同时在移动目标上运行MonoVM,而不需要改变现有的工具。dotnet-dsrouter
运行一个本地IPC服务器,将诊断工具的所有流量路由到模拟器/设备上的MonoVM中运行的DiagnosticsServer。 - 在MonoVM中使用基于组件的架构实现EventPipe/DiagnosticsServer。
- 实现/扩展基于文件会话的诊断环境。
iOS CPU采样(SpeedScope)
下面的图片展示了在SpeedScope中查看的iOS启动CPU采样会话的一部分。
Android CPU采样(PerfView)
下图展示了PerfView中查看的Android CPU采样(主线程处于无限睡眠状态)。
运行时间。CodeGen
RyuJIT中做了以下修改。
社区贡献
- 删除了未使用的dummyBB变量 github.com/dotnet/runt…
- 删除了未使用的读取 big-endian 格式的整数的函数 github.com/dotnet/runt…
- 将TYP_FLOAT传递给gtNewDconNode,而不是创建一个新的范围 github.com/dotnet/runt…
动态PGO github.com/dotnet/runt…
- 修改inlinee比例计算 github.com/dotnet/runt…
- 更新optReachable与排除块检查 github.com/dotnet/runt…
- 围绕空流优化泛化分支 github.com/dotnet/runt…
- 为新的GetLikelyClass PGO记录类型添加MCS jitflags支持 github.com/dotnet/runt…
- 普及尾部调用后有效IR的检查,以支持crossgen2的确定性 github.com/dotnet/runt…
- 更普遍的价值类 devirtualization github.com/dotnet/runt…
- 链式保护的devirtualization github.com/dotnet/runt…](user-images.githubusercontent.com/63486087/12…)
JIT循环优化 github.com/dotnet/runt…
- 改进的循环反转在BenchE中显示出良好的性能改进 github.com/dotnet/runt…<img src="user-images.githubusercontent.com/63486087/12…" width="600″ height="120″>
- 缩放克隆的循环块权重 github.com/dotnet/runt…
- 在克隆循环时不要重新计算preds列表,以保留边上现有的剖面数据 github.com/dotnet/runt…
- 改进DOT流图的转储 github.com/dotnet/runt…
- 改进循环解卷的文档 github.com/dotnet/runt…
LSRA github.com/dotnet/runt…
- 在 "分配寄存器 "表中包括寄存器选择启发式方法 github.com/dotnet/runt… 新旧表的差异。
在寄存器中保留结构 github.com/dotnet/runt…
- 为寄存器中的结构准备JIT后端 github.com/dotnet/runt…
- 修复结构enreg的有效性 github.com/dotnet/runt…
- 改进结构inits以保持ASG结构(LCL_VAR, 0)为STORE_LCL_VAR结构(0) github.com/dotnet/runt…
优化和调试经验
- 识别并处理nint/nuint的Vector64/128/256 github.com/dotnet/runt…
- 添加clrjit.natvis文件以获得更好的调试体验 github.com/dotnet/runt… jitstd::list的示例可视化器,以及RefPosition和里面registerAssignment的分解以显示所有的寄存器。
SIMD
对某些涉及SIMD或HWIntrinsics的方法进行内嵌,现在应该可以改善代码生成和性能。我们看到了高达95%的改进。
总结
就功能的广度和数量而言,.NET 6预览版5也许是最大的一次预览。你可以看到Roslyn功能对底层库功能的影响有多大,有源码生成器和分析器。未来已经真正到来。我们现在有一个非常有能力的编译器工具链,使我们能够产生高度优化和正确的代码,并使你自己的项目有完全相同的体验。
现在是开始测试.NET 6的好时机,对我们来说,现在还很早,可以根据你的反馈采取行动。很难想象,虽然我们要到2021年11月才发货,但反馈窗口很快就会缩小到只有高严重度的问题。团队的工作是提前一个半月进行预览,并将很快转为主要关注质量问题。如果可以的话,请试一试.NET 6。
谢谢你成为一名.NET开发者。