今天我們發布了 .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 預覽版。現在,讓我們了解此版本中的一些最新更新。https://devblogs.microsoft.com/dotnet/dotnet-7-generic-math/?ocid=AID3042760https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760https://mcr.microsoft.com/catalog?search=dotnet/https://github.com/dotnet/core/blob/master/release-notes/7.0/https://github.com/dotnet/core/tree/master/release-notes/7.0https://github.com/dotnet/core/blob/main/release-notes/7.0/known-issues.mdhttps://github.com/dotnet/core/issueshttps://visualstudio.com/previewVisual 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/68056System.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 }");valueisDerived;//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 }");valueisDerived;//true類型鑑別器標識符也可以是整數,因此以下形式是有效的:[JsonDerivedType(typeof(Derived1), 0)][JsonDerivedType(typeof(Derived2), 1)][JsonDerivedType(typeof(Derived3), 2)]publicclassBase{}JsonSerializer.Serialize<Base>(newDerived2());//{"$type":1,...}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 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);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▌源生成改進
添加了對 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(newMyPoco{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);//guaranteedtoread100bytesfromthefile新的 ReadAtLeast 方法將至少讀取請求的字節數。如果有更多數據可用,它可以讀取更多數據,直到緩衝區的大小。如果流在讀取請求的字節之前結束,則會引發 EndOfStreamException(在高級情況下,當您想要 ReadAtLest 的好處但您還想自己處理流結束場景時,您可以選擇不引發異常)。
using FileStream f = File.Open("readme.md");byte[] buffer = new byte[100];int bytesRead = f.ReadAtLeast(buffer, 10);//10<=bytesRead<=100https://github.com/dotnet/runtime/issues/16598RegexGenerator 的新 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 將開始支持更多類型,而不需要每個數字類型都獲得顯式支持。
在 .NET 7 中,我們對實現進行了改進並響應了社區的反饋。有關更改和可用 API 的更多信息,請參閱我們的通用數學特定公告。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 調用成員時的性能改進
當對同一個成員進行多次調用時,使用反射來調用成員(無論是方法、構造函數還是屬性 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; }}https://github.com/dotnet/runtime/pull/67917
常見用例包括:
將電子郵件分類為垃圾郵件或非垃圾郵件
從客戶評論中分析情緒是積極的還是消極的
應用標籤來支持工單
文本分類是分類的一個子集,因此今天您可以使用 ML.NET 中現有的分類算法來解決文本分類問題。然而,這些算法並沒有解決文本分類以及現代深度學習技術的常見挑戰。
我們很高興推出 ML.NET 文本分類 API,該 API 使您可以更輕鬆地訓練自定義文本分類模型,並將用於自然語言處理的最新最先進的深度學習技術引入 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」對象的空值檢查將空值檢查移動到循環外的對象上(請參閱性能改進細節)。

https://github.com/singleaccretionhttps://github.com/dotnet/runtime/pulls?q=is%3Apr+is%3Aclosed+label%3Aarea-CodeGen-coreclr+closed%3A2022-04-18..2022-05-24+author%3Asingleaccretion+
https://github.com/dotnet/runtime/pull/68447https://github.com/dotnet/runtime/pull/68641
https://github.com/dotnet/runtime/pull/68592https://github.com/Sandreenkohttps://github.com/dotnet/runtime/pull/59315https://github.com/hez2010https://github.com/dotnet/runtime/pull/68475
https://github.com/anthonycaninohttps://github.com/aromaahttps://github.com/dotnet/runtime/pull/68363Arm64:讓 CpBlkUnroll 和 InitBlkUnroll 使用 SIMD 寄存器:https://github.com/dotnet/runtime/pull/68085https://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
https://github.com/dotnet/runtime/pull/67930
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
#67182 在 x64 上將 shlx、sarx、shrx 優化為 x64 上的 mov+shl、sar 或 shr 到 shlx、sarx 或 shrx。@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#68105:
https://github.com/dotnet/runtime/pull/68105
PR#69034 :
https://github.com/dotnet/runtime/pull/69034
隨着社區增加了對 JIT 代碼庫的貢獻,重組和現代化我們的代碼庫以使我們的貢獻者能夠輕鬆地增加和快速開發代碼變得非常重要。在 Preview 5 中,我們在內部做了大量工作,清理了 JIT 的中間表示,並消除了過去設計決策帶來的限制。在許多情況下,這項工作導致 JIT 本身的內存使用更少和吞吐量更高,而在其他情況下,它導致了更好的代碼質量。以下是一些亮點:以上允許我們在使用 byte/sbyte/short/ushort 類型的參數內聯函數時消除 JIT 內聯中的舊限制,從而提高代碼質量(允許內聯替換小參數 #69068)
需要改進的一個領域是更好地理解涉及讀取和寫入結構和結構字段的不安全代碼。@SingleAccretion 通過將 JIT 的內部模型轉換為更通用的「物理」模型,在這一領域做出了巨大的改變。這為 JIT 使用 struct reinterpretation 等功能更好地推理不安全代碼鋪平了道路:
為 VNF_BitCast 實現常量摺疊 #68979還進行了其他小的清理以簡化 JIT IR:
在內聯候選參數中替換 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 Target Framework Moniker (TFM)。例如:
<TargetFramework>net7.0</TargetFramework>全套 .NET 7 TFM,包括特定於操作的 TFM。
我們希望從 .NET 6 升級到 .NET 7 應該很簡單。請報告您在使用 .NET 7 測試現有應用程序的過程中發現的任何重大更改。
.NET 7 是一個短期支持 (STS) 版本,這意味着它將在發布之日起 18 個月內獲得免費支持和補丁。需要注意的是,所有版本的質量都是相同的。唯一的區別是支撐的長度。有關 .NET 支持政策的更多信息,請參閱 .NET 和 .NET Core 官方支持政策。我們最近將「Current當前」名稱更改為「短期支持 (STS)」。我們正在推出這一變化。https://dotnet.microsoft.com/platform/support/policy/dotnet-core?ocid=AID3042760https://github.com/dotnet/core/pull/7517您可以通過閱讀 .NET 7 中的重大更改文檔找到最新的 .NET 7 重大更改列表。它按區域和版本列出了重大更改,並附有詳細說明的鏈接。
要查看提出了哪些重大更改但仍在審核中,請關注 Proposed .NET Breaking Changes GitHub 問題。.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
ASP.NET Core 7 和 Blazor 路線圖:https://github.com/dotnet/aspnetcore/issues/39504https://docs.microsoft.com/ef/core/what-is-new/ef-core-7.0/planhttps://github.com/dotnet/machinelearning/blob/main/ROADMAP.mdhttps://github.com/dotnet/maui/wiki/Roadmaphttps://github.com/dotnet/winforms/blob/main/docs/roadmap.mdhttps://github.com/dotnet/wpf/blob/main/roadmap.mdhttps://github.com/NuGet/Home/issues/11571https://github.com/dotnet/roslyn/blob/main/docs/Language Feature Status.mdhttps://github.com/dotnet/core/blob/main/roadmap.md我們感謝您對 .NET 的所有支持和貢獻。請嘗試 .NET 7 Preview 5 並告訴我們您的想法!
https://dotnet.microsoft.com/thanks?ocid=AID3042760https://dotnet.microsoft.com/download/dotnet/7.0?ocid=AID3042760謝謝你讀完了本文!歡迎在評論區留言分享你的想法,並且轉發到朋友圈。如果你對本文青睞有加,想要轉載到自己的平台,請在後台回復「轉載」與我們取得聯繫!
長按識別二維碼
關注微軟中國MSDN