官宣.NET 7 预览版5
共 16648字,需浏览 34分钟
·
2022-06-24 19:24
您可以下载适用于 Windows、macOS 和 Linux 的 .NET 7 Preview 5。
安装程序和二进制文件
容器图像
Linux 软件包
发行说明
已知的问题
GitHub 问题跟踪器
通用数学: https://devblogs.microsoft.com/dotnet/dotnet-7-generic-math/?ocid=AID3042760 .NET 7 Preview 5: https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760 安装程序和二进制文件: https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760 容器图像: https://mcr.microsoft.com/catalog?search=dotnet/ Linux 软件包: https://github.com/dotnet/core/blob/master/release-notes/7.0/ 发行说明: https://github.com/dotnet/core/tree/master/release-notes/7.0 已知的问题: https://github.com/dotnet/core/blob/main/release-notes/7.0/known-issues.md GitHub 问题跟踪器: https://github.com/dotnet/core/issues 预览频道版本: https://visualstudio.com/preview Visual Studio 2022 for Mac 预览版: https://visualstudio.microsoft.com/vs/mac/preview/
可观察性
可观察性的目标是帮助您更好地了解应用程序在规模和技术复杂性增加时的状态。
▌公开高效的 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
#68056:
https://github.com/dotnet/runtime/issues/68056
System.Text.Json
多态性
System.Text.Json 现在支持使用属性注释对多态类型层次结构进行序列化和反序列化:
[JsonDerivedType(typeof(Derived))]
public class Base
{
public int X { get; set; }
}
public class Derived : Base
{
public int Y { get; set; }
}
Base value = new Derived();
JsonSerializer.Serialize<Base>(value); // { "X" : 0, "Y" : 0 }
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; }
}
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
直到今天,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 string
ArrayPool<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);
#54410: https://github.com/dotnet/runtime/issues/54410
Utf8JsonReader.GetString(): https://docs.microsoft.com/dotnet/api/system.text.json.utf8jsonreader.getstring?view=net-6.0?ocid=AID3042760
▌源生成改进
例如:
[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 NotSupportedException
JsonSerializer.Serialize(new MyPoco { Data = ... }, MyContext.MyPoco);
#59268:
https://github.com/dotnet/runtime/issues/59268
#59954:
https://github.com/dotnet/runtime/issues/59954
#53539:
https://github.com/dotnet/runtime/issues/53539
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
#16598: https://github.com/dotnet/runtime/issues/16598
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 中正在运行的新分析器:
#69872:
https://github.com/dotnet/runtime/pull/69872
.NET 7 中的正则表达式改进中,Stephen Toub 描述了新的 RegexGenerator 源生成器:
https://devblogs.microsoft.com/dotnet/regular-expression-improvements-in-dotnet-7/#source-generation?ocid=AID3042760
了解更多:
https://docs.microsoft.com/dotnet/csharp/language-reference/configure-language-version?ocid=AID3042760
▌代码修复器
代码修复程序也包含在 .NET 7 中,它做了两件事。首先,它建议使用 RegexGenerator 源生成器方法,并为您提供覆盖默认名称的选项。然后它用对新方法的调用替换原始代码。
以下是 Visual Studio 中正在运行的新代码修复程序:
通用数学
在 .NET 6 中,我们预览了一个名为 Generic Math 的功能,它允许 .NET 开发人员在通用代码中利用静态 API,包括运算符。此功能将直接使可以简化代码库的 API 作者受益。其他开发人员将间接受益,因为他们使用的 API 将开始支持更多类型,而不需要每个数字类型都获得显式支持。
Generic Math: https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/?ocid=AID3042760 通用数学特定公告:
https://devblogs.microsoft.com/dotnet/dotnet-7-generic-math/?ocid=AID3042760
System.Reflection 调用成员时的性能改进
使用 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;
}
}
#67917 : https://github.com/dotnet/runtime/pull/67917
ML.NET 文本分类 API
常见用例包括:
将电子邮件分类为垃圾邮件或非垃圾邮件
从客户评论中分析情绪是积极的还是消极的
应用标签来支持工单
文本分类是分类的一个子集,因此今天您可以使用 ML.NET 中现有的分类算法来解决文本分类问题。然而,这些算法并没有解决文本分类以及现代深度学习技术的常见挑战。
我们很高兴推出 ML.NET 文本分类 API,该 API 使您可以更轻松地训练自定义文本分类模型,并将用于自然语言处理的最新最先进的深度学习技术引入 ML.NET。
有关更多详细信息,请参阅我们的 ML.NET 特定公告。
ML.NET 特定公告: https://devblogs.microsoft.com/dotnet/introducing-the-ml-dotnet-text-classification-api-preview/?ocid=AID3042760
代码生成
非常感谢社区贡献者。
@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”对象的空值检查将空值检查移动到循环外的对象上(请参阅性能改进细节)。
@singleaccretion: https://github.com/singleaccretion 23 项 PR 贡献: https://github.com/dotnet/runtime/pulls?q=is%3Apr+is%3Aclosed+label%3Aarea-CodeGen-coreclr+closed%3A2022-04-18..2022-05-24+author%3Asingleaccretion+
#68447: https://github.com/dotnet/runtime/pull/68447 #68641: https://github.com/dotnet/runtime/pull/68641
#68592: https://github.com/dotnet/runtime/pull/68592 @Sandreenko: https://github.com/Sandreenko #59315: https://github.com/dotnet/runtime/pull/59315 @hez2010: https://github.com/hez2010 #68475: https://github.com/dotnet/runtime/pull/68475
@anthonycanino: https://github.com/anthonycanino @aromaa: https://github.com/aromaa @ta264: https://github.com/ta264 #68363: https://github.com/dotnet/runtime/pull/68363 Arm64:让 CpBlkUnroll 和 InitBlkUnroll 使用 SIMD 寄存器: https://github.com/dotnet/runtime/pull/68085 性能改进细节: https://pvscmdupload.blob.core.windows.net/autofilereport/autofilereports/04_28_2022/refs/heads/main_arm64_Windows 10.0.19041_Improvement/System.Numerics.Tests.Perf_Matrix4x4.html
#67930 处理循环克隆的更多场景: https://github.com/dotnet/runtime/pull/67930
#68588 提升“this”对象的空值检查: https://github.com/dotnet/runtime/pull/68588
性能改进细节: https://pvscmdupload.blob.core.windows.net/autofilereport/autofilereports/05_03_2022/refs/heads/main_x64_Windows 10.0.18362_Improvement/System.Text.Encodings.Web.Tests.Perf_Encoders.html
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 编译。
#67182 在 x64 上将 shlx:
https://github.com/dotnet/runtime/pull/67182
sarx:
https://github.com/dotnet/runtime/pull/67182
shrx 优化为 x64 :
https://github.com/dotnet/runtime/pull/67182
#68091:
https://github.com/dotnet/runtime/pull/68091
@anthonycanino :
https://github.com/anthonycanino
#68677 :
https://github.com/dotnet/runtime/pull/68677
@aromaa :
https://github.com/aromaa
#66965:
https://github.com/dotnet/runtime/pull/66965
@ta264:
https://github.com/ta264
#68046 :
https://github.com/dotnet/runtime/pull/68046
一般优化
PR#68105 启用了多个嵌套的“no GC”区域请求。 PR#69034 删除了“提升参数”尾调用限制。
PR#68105:
https://github.com/dotnet/runtime/pull/68105
PR#69034 :
https://github.com/dotnet/runtime/pull/69034
现代化 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 中删除存储作为调用的操作数
#68524:
https://github.com/dotnet/runtime/pull/68524
#68140:
https://github.com/dotnet/runtime/pull/68140
#68748:
https://github.com/dotnet/runtime/pull/68748
#69068:
https://github.com/dotnet/runtime/pull/69068
@SingleAccretion :
https://github.com/SingleAccretion
#68712:
https://github.com/dotnet/runtime/pull/68712
#68979:
https://github.com/dotnet/runtime/pull/68979
#68617:
https://github.com/dotnet/runtime/pull/68617
#69117:
https://github.com/dotnet/runtime/pull/69117
#68460 :
https://github.com/dotnet/runtime/pull/68460
启用库修剪
正如我们之前所描述的,修剪让 SDK 从您的自包含应用程序中删除未使用的代码,以使它们更小。但是,修剪警告可能表明应用程序与修剪不兼容。为了使应用程序兼容,它们的所有引用也必须兼容。
为此,我们需要库也采用修剪。在预览版 5 中,我们努力使用 Roslyn 分析器更轻松地查找和修复库中的修剪警告。要查看库的修剪警告,请将 <IsTrimmable>true</IsTrimmable> 添加到项目文件中。修复警告后,使用您的库修剪的应用程序将更小并且与修剪兼容。请参阅准备 .NET 库以进行修剪 - .NET | Microsoft Docs 了解有关库修剪的更多信息。
修剪: https://docs.microsoft.com/dotnet/core/deploying/trimming/trim-self-contained?ocid=AID3042760 请参阅准备 .NET 库以进行修剪 - .NET | Microsoft Docs : https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming?ocid=AID3042760
面向 .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 和 .NET Core 官方支持政策: https://dotnet.microsoft.com/platform/support/policy/dotnet-core?ocid=AID3042760 推出这一变化: https://github.com/dotnet/core/pull/7517
重大变化
您可以通过阅读 .NET 7 中的重大更改文档找到最新的 .NET 7 重大更改列表。它按区域和版本列出了重大更改,并附有详细说明的链接。
.NET 7 重大更改列表:
https://docs.microsoft.com/dotnet/core/compatibility/7.0?ocid=AID3042760
Proposed .NET Breaking Changes GitHub 问题:
https://github.com/dotnet/core/issues/7131
路线图
.NET 版本包括产品、库、运行时和工具,代表了 Microsoft 内外多个团队之间的协作。您可以通过阅读产品路线图了解有关这些领域的更多信息:
ASP.NET Core 7 和 Blazor 路线图
EF 7 路线图
机器学习网络
.NET MAUI
WinForms
WPF
NuGet
Roslyn
Runtime
ASP.NET Core 7 和 Blazor 路线图: https://github.com/dotnet/aspnetcore/issues/39504 EF 7 路线图: https://docs.microsoft.com/ef/core/what-is-new/ef-core-7.0/plan 机器学习网络: https://github.com/dotnet/machinelearning/blob/main/ROADMAP.md .NET MAUI: https://github.com/dotnet/maui/wiki/Roadmap WinForms: https://github.com/dotnet/winforms/blob/main/docs/roadmap.md WPF: https://github.com/dotnet/wpf/blob/main/roadmap.md NuGet: https://github.com/NuGet/Home/issues/11571 Roslyn: https://github.com/dotnet/roslyn/blob/main/docs/Language Feature Status.md Runtime: https://github.com/dotnet/core/blob/main/roadmap.md
我们感谢您对 .NET 的所有支持和贡献。请尝试 .NET 7 Preview 5 并告诉我们您的想法!
感谢: https://dotnet.microsoft.com/thanks?ocid=AID3042760 尝试 .NET 7 Preview 5: https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760