明天咱们公布了 .NET 7 预览版 5。.NET 7 的这个预览版包含对通用数学的改良,不便了 API 作者,使其更轻松,一个新的 ML.NET 文本分类 API,减少了最先进的深度学习技术 ,对于自然语言解决,对源代码生成器的各种改良以及用于 RegexGenerator 的新 Roslyn 分析器和修复器,以及在 CodeGen、可察看性、JSON 序列化/反序列化和应用流方面的多项性能改良。
您能够下载实用于 Windows、macOS 和 Linux 的 .NET 7 Preview 5。

  • 安装程序和二进制文件
  • 容器图像
  • Linux 软件包
  • 发行阐明
  • 已知的问题
  • GitHub 问题跟踪器

.NET 7 预览版 5 已通过 Visual Studio 17.3 预览版 2 进行测试。如果您想将 .NET 7 与 Visual Studio 系列产品一起应用,咱们建议您应用预览频道版本。如果您应用的是 macOS,咱们倡议应用最新的 Visual Studio 2022 for Mac 预览版。当初,让咱们理解此版本中的一些最新更新。

可察看性

可察看性的指标是帮忙您更好地理解应用程序在规模和技术复杂性减少时的状态。

▌公开高效的 ActivityEvent 和 ActivityLink 标记枚举器办法

#68056

公开的办法可用于在性能要害场景中枚举 Tag 对象,而无需任何额定的调配和疾速的我的项目拜访。

var tags = new List<KeyValuePair<string, object?>>(){    new KeyValuePair<string, object?>("tag1", "value1"),    new KeyValuePair<string, object?>("tag2", "value2"),};ActivityLink link = new ActivityLink(default, new ActivityTagsCollection(tags));foreach (ref readonly KeyValuePair<string, object?> tag in link.EnumerateTagObjects()){    // Consume the link tags without any extra allocations or value copying.}            ActivityEvent e = new ActivityEvent("SomeEvent", tags: new ActivityTagsCollection(tags));foreach (ref readonly KeyValuePair<string, object?> tag in e.EnumerateTagObjects()){    // Consume the event's tags without any extra allocations or value copying.} 

可察看性:

https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/?ocid=AID3042760

System.Text.Json多态性

#63747
System.Text.Json 当初反对应用属性正文对多态类型层次结构进行序列化和反序列化:

[JsonDerivedType(typeof(Derived))]public class Base{    public int X { get; set; }}public class Derived : Base{    public int Y { get; set; }}

此配置为 Base 启用多态序列化,特地是在运行时类型为 Derived 时:

Base value = new Derived();JsonSerializer.Serialize<Base>(value); // { "X" : 0, "Y" : 0 }

请留神,这不会启用多态反序列化,因为无效负载将作为 Base 往返:

Base value = JsonSerializer.Deserialize<Base>(@"{ ""X"" : 0, ""Y"" : 0 }");value is Derived; // false

▌应用类型鉴别器
要启用多态反序列化,用户须要为派生类指定类型鉴别器:

[JsonDerivedType(typeof(Base), typeDiscriminator: "base")][JsonDerivedType(typeof(Derived), typeDiscriminator: "derived")]public class Base{    public int X { get; set; }}public class Derived : Base{    public int Y { get; set; }}

当初将收回 JSON 以及类型鉴别器元数据:

Base value = new Derived();JsonSerializer.Serialize<Base>(value); // { "$type" : "derived", "X" : 0, "Y" : 0 }

可用于多态反序列化值:

Base value = JsonSerializer.Deserialize<Base>(@"{ ""$type"" : ""derived"", ""X"" : 0, ""Y"" : 0 }");value is Derived; // true

类型鉴别器标识符也能够是整数,因而以下模式是无效的:

[JsonDerivedType(typeof(Derived1), 0)][JsonDerivedType(typeof(Derived2), 1)][JsonDerivedType(typeof(Derived3), 2)]public class Base { }JsonSerializer.Serialize<Base>(new Derived2()); // { "$type" : 1, ... }#63747:https://github.com/dotnet/runtime/issues/63747

▌Utf8JsonReader.CopyString

#54410
直到明天,Utf8JsonReader.GetString() 始终是用户应用解码后的 JSON 字符串的惟一形式。这将始终调配一个新字符串,这可能不适宜某些性能敏感的应用程序。新蕴含的 CopyString 办法容许将未本义的 UTF-8 或 UTF-16 字符串复制到用户领有的缓冲区:

int valueLength = reader.HasReadOnlySequence ? checked((int)ValueSequence.Length) : ValueSpan.Length;char[] buffer = ArrayPool<char>.Shared.Rent(valueLength);int charsRead = reader.CopyString(buffer);ReadOnlySpan<char> source = buffer.Slice(0, charsRead);ParseUnescapedString(source); // handle the unescaped JSON stringArrayPool<char>.Shared.Return(buffer);

或者如果解决 UTF-8 更可取:

ReadOnlySpan<byte> source = stackalloc byte[0];if (!reader.HasReadOnlySequence && !reader.ValueIsEscaped){    source = reader.ValueSpan; // No need to copy to an intermediate buffer if value is span without escape sequences}else{    int valueLength = reader.HasReadOnlySequence ? checked((int)ValueSequence.Length) : ValueSpan.Length;    Span<byte> buffer = valueLength <= 256 ? stackalloc byte[256] : new byte[valueLength];    int bytesRead = reader.CopyString(buffer);    source = buffer.Slice(0, bytesRead);}ParseUnescapedBytes(source);

▌源生成改良

增加了对 IAsyncEnumerable<T> (#59268)、JsonDocument(#59954) 和 DateOnly/TimeOnly(#53539) 类型的源代码生成反对。
例如:

[JsonSerializable(typeof(typeof(MyPoco))]public class MyContext : JsonSerializerContext {}public class MyPoco{    // Use of IAsyncEnumerable that previously resulted     // in JsonSerializer.Serialize() throwing NotSupportedException     public IAsyncEnumerable<int> Data { get; set; } }// It now works and no longer throws NotSupportedExceptionJsonSerializer.Serialize(new MyPoco { Data = ... }, MyContext.MyPoco);

System.IO.Stream 、 ReadExactly 和 ReadAtLeast

#16598

应用 Stream.Read() 时最常见的谬误之一是 Read() 返回的数据可能比 Stream 中可用的数据少,而数据也比传入的缓冲区少。即便对于意识到这一点的程序员来说, 每次他们想从 Stream 中读取时都编写雷同的循环很烦人。

为了解决这种状况,咱们在 System.IO.Stream 基类中增加了新办法:

namespace System.IO;public partial class Stream{    public void ReadExactly(Span<byte> buffer);    public void ReadExactly(byte[] buffer, int offset, int count);    public ValueTask ReadExactlyAsync(Memory<byte> buffer, CancellationToken cancellationToken = default);    public ValueTask ReadExactlyAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default);    public int ReadAtLeast(Span<byte> buffer, int minimumBytes, bool throwOnEndOfStream = true);    public ValueTask<int> ReadAtLeastAsync(Memory<byte> buffer, int minimumBytes, bool throwOnEndOfStream = true, CancellationToken cancellationToken = default);}

新的 ReadExactly 办法保障精确读取申请的字节数。如果流在读取申请的字节之前完结,则抛出 EndOfStreamException。

using FileStream f = File.Open("readme.md");byte[] buffer = new byte[100];f.ReadExactly(buffer); // guaranteed to read 100 bytes from the file

新的 ReadAtLeast 办法将至多读取申请的字节数。如果有更多数据可用,它能够读取更多数据,直到缓冲区的大小。如果流在读取申请的字节之前完结,则会引发 EndOfStreamException(在高级状况下,当您想要 ReadAtLest 的益处但您还想本人解决流完结场景时,您能够抉择不引发异样)。

using FileStream f = File.Open("readme.md");byte[] buffer = new byte[100];int bytesRead = f.ReadAtLeast(buffer, 10);// 10 <= bytesRead <= 100

RegexGenerator 的新 Roslyn 分析器和修复器

#69872

在 .NET 7 中的正则表达式改良中,Stephen Toub 形容了新的 RegexGenerator 源生成器,它容许您在编译时动态生成正则表达式,从而取得更好的性能。要利用这一点,首先您必须在代码中找到能够应用它的地位,而后对每个代码进行更改。这听起来像是 Roslyn 分析器和修复器的完满工作,所以咱们在 Preview 5 中增加了一个。

▌分析仪

新的分析器蕴含在 .NET 7 中,将搜寻能够转换为应用 RegexGenerator 源生成器的 Regex 用处。分析器将检测 Regex 构造函数的应用,以及满足以下条件的 Regex 静态方法的应用:

提供的参数在编译时具备已知值。源代码生成器的输入取决于这些值,因而必须在编译时晓得它们。

它们是面向 .NET 7 的应用程序的一部分。新的分析器蕴含在 .NET 7 指标包中,只有面向 .NET 7 的应用程序才有资格应用此分析器。

LangVersion(理解更多)高于 10。目前正则表达式源生成器须要将 LangVersion 设置为预览。

上面是 Visual Studio 中正在运行的新分析器:

▌代码修复器

代码修复程序也蕴含在 .NET 7 中,它做了两件事。首先,它倡议应用 RegexGenerator 源生成器办法,并为您提供笼罩默认名称的选项。而后它用对新办法的调用替换原始代码。

以下是 Visual Studio 中正在运行的新代码修复程序:

通用数学

在 .NET 6 中,咱们预览了一个名为 Generic Math 的性能,它容许 .NET 开发人员在通用代码中利用动态 API,包含运算符。此性能将间接使能够简化代码库的 API 作者受害。其余开发人员将间接受害,因为他们应用的 API 将开始反对更多类型,而不须要每个数字类型都取得显式反对。

在 .NET 7 中,咱们对实现进行了改良并响应了社区的反馈。无关更改和可用 API 的更多信息,请参阅咱们的通用数学特定布告。

System.Reflection 调用成员时的性能改良

#67917
当对同一个成员进行屡次调用时,应用反射来调用成员(无论是办法、构造函数还是属性 gettersetter)的开销已大大减少。典型增益快 3-4 倍。
应用 BenchmarkDotNet 包:

using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Running;using System.Reflection;namespace ReflectionBenchmarks{    internal class Program    {        static void Main(string[] args)        {            BenchmarkRunner.Run<InvokeTest>();        }    }    public class InvokeTest    {        private MethodInfo? _method;        private object[] _args = new object[1] { 42 };        [GlobalSetup]        public void Setup()        {            _method = typeof(InvokeTest).GetMethod(nameof(InvokeMe), BindingFlags.Public | BindingFlags.Static)!;        }        [Benchmark]        // *** This went from ~116ns to ~39ns or 3x (66%) faster.***        public void InvokeSimpleMethod() => _method!.Invoke(obj: null, new object[] { 42 });        [Benchmark]        // *** This went from ~106ns to ~26ns or 4x (75%) faster. ***        public void InvokeSimpleMethodWithCachedArgs() => _method!.Invoke(obj: null, _args);        public static int InvokeMe(int i) => i;    }}

ML.NET 文本分类 API

文本分类是将标签或类别利用于文本的过程。
常见用例包含:

  • 将电子邮件分类为垃圾邮件或非垃圾邮件
  • 从客户评论中剖析情绪是踊跃的还是消极的
  • 利用标签来反对工单

文本分类是分类的一个子集,因而明天您能够应用 ML.NET 中现有的分类算法来解决文本分类问题。然而,这些算法并没有解决文本分类以及古代深度学习技术的常见挑战。

咱们很快乐推出 ML.NET 文本分类 API,该 API 使您能够更轻松地训练自定义文本分类模型,并将用于自然语言解决的最新最先进的深度学习技术引入 ML.NET。

无关更多详细信息,请参阅咱们的 ML.NET 特定布告。

代码生成

非常感谢社区贡献者。

@singleaccretion 在预览版 5 期间做出了 23 项 PR 奉献,其中亮点是:

改良冗余分支优化以解决更多副作用 #68447

PUTARG_STK/x86: 标记 push [mem] 候选 reg 可选 #68641

在 LCL_FLD 上复制流传 #68592

@Sandreenko 实现容许 StoreLclVar src 成为 IND/FLD #59315。@hez2010 修复了 #68475 中的 CircleInConvex 测试。

来自@anthonycanino、@aromaa 和@ta264 的更多奉献蕴含在前面的局部中。

▌Arm64

#68363 合并“msub”(将两个寄存器值相乘,从第三个寄存器值中减去乘积)和“madd”(将两个寄存器值相乘,增加第三个寄存器值)逻辑。

Arm64:让 CpBlkUnroll 和 InitBlkUnroll 应用 SIMD 寄存器来初始化复制小于 128 字节的内存块(请参阅性能改良细节)。

▌循环优化

#67930 解决循环克隆的更多场景当初反对以 > 1 的增量向后或向前的循环(请参阅性能改良详细信息)。

#68588 晋升“this”对象的空值查看将空值查看挪动到循环外的对象上(请参阅性能改良细节)。

x86/x64 优化

  • #67182 在 x64 上将 shlx、sarx、shrx 优化为 x64 上的 mov+shl、sar 或 shr 到 shlx、sarx 或 shrx。
  • #68091为 x64 启用了 UMOD 优化。
  • @anthonycanino 在 #68677中增加了 X86Serialize 硬件外在。
  • @aromaa 在 #66965中将 bswap+mov 优化为movbe。
  • @ta264 修复了 #68046 中 clr.alljits 子集的linux-x86 编译。

个别优化

  • PR#68105 启用了多个嵌套的“no GC”区域申请。
  • PR#69034 删除了“晋升参数”尾调用限度。

现代化 JIT

随着社区减少了对 JIT 代码库的奉献,重组和现代化咱们的代码库以使咱们的贡献者可能轻松地减少和疾速开发代码变得十分重要。
在 Preview 5 中,咱们在外部做了大量工作,清理了 JIT 的两头示意,并打消了过来设计决策带来的限度。在许多状况下,这项工作导致 JIT 自身的内存应用更少和吞吐量更高,而在其余状况下,它导致了更好的代码品质。以下是一些亮点:

  • 删除 CLS_VAR #68524
  • 删除 GT_ARGPLACE #68140
  • 删除 GT_PUTARG_TYPE #68748
    以上容许咱们在应用 byte/sbyte/short/ushort 类型的参数内联函数时打消 JIT 内联中的旧限度,从而进步代码品质(容许内联替换小参数 #69068)

须要改良的一个畛域是更好地了解波及读取和写入构造和构造字段的不平安代码。@SingleAccretion 通过将 JIT 的外部模型转换为更通用的“物理”模型,在这一畛域做出了微小的扭转。这为 JIT 应用 struct reinterpretation 等性能更好地推理不平安代码铺平了路线:

  • 物理值编号 #68712
  • 为 VNF_BitCast 实现常量折叠 #68979

还进行了其余小的清理以简化 JIT IR:

  • 删除 GTF_LATE_ARG #68617
  • 在内联候选参数中替换 GT_RET_EXPR #69117
  • 在 LIR #68460 中删除存储作为调用的操作数

启用库修剪

正如咱们之前所形容的,修剪让 SDK 从您的自蕴含应用程序中删除未应用的代码,以使它们更小。然而,修剪正告可能表明应用程序与修剪不兼容。为了使应用程序兼容,它们的所有援用也必须兼容。

为此,咱们须要库也采纳修剪。在预览版 5 中,咱们致力应用 Roslyn 分析器更轻松地查找和修复库中的修剪正告。要查看库的修剪正告,请将 <IsTrimmable>true</IsTrimmable> 增加到我的项目文件中。修复正告后,应用您的库修剪的应用程序将更小并且与修剪兼容。请参阅筹备 .NET 库以进行修剪 - .NET | Microsoft Docs 理解无关库修剪的更多信息。

面向 .NET 7

要面向 .NET 7,您须要在我的项目文件中应用 .NET 7 Target Framework Moniker (TFM)。例如:

<TargetFramework>net7.0</TargetFramework>

全套 .NET 7 TFM,包含特定于操作的 TFM。

  • net7.0
  • net7.0-安卓
  • net7.0-ios
  • net7.0-maccatalyst
  • net7.0-macos
  • net7.0-tvos
  • net7.0-windows
    咱们心愿从 .NET 6 降级到 .NET 7 应该很简略。请报告您在应用 .NET 7 测试现有应用程序的过程中发现的任何重大更改。

反对

.NET 7 是一个短期反对 (STS) 版本,这意味着它将在公布之日起 18 个月内取得收费反对和补丁。须要留神的是,所有版本的品质都是雷同的。惟一的区别是撑持的长度。无关 .NET 反对政策的更多信息,请参阅 .NET 和 .NET Core 官网反对政策。
咱们最近将“Current以后”名称更改为“短期反对 (STS)”。咱们正在推出这一变动。

重大变动

您能够通过浏览 .NET 7 中的重大更改文档找到最新的 .NET 7 重大更改列表。它按区域和版本列出了重大更改,并附有具体阐明的链接。

要查看提出了哪些重大更改但仍在审核中,请关注 Proposed .NET Breaking Changes GitHub 问题。

路线图

.NET 版本包含产品、库、运行时和工具,代表了 Microsoft 内外多个团队之间的合作。您能够通过浏览产品路线图理解无关这些畛域的更多信息:

  • ASP.NET Core 7 和 Blazor 路线图
  • EF 7 路线图
  • 机器学习网络
  • .NET MAUI
  • WinForms
  • WPF
  • NuGet
  • Roslyn
  • Runtime

咱们感谢您对 .NET 的所有反对和奉献。请尝试 .NET 7 Preview 5 并通知咱们您的想法!


长按辨认二维码
关注微软中国MSDN

查看.NET 7 预览版5