.NET 6 預覽版 5 釋出

MicrosoftReactor發表於2021-08-02

很高興.NET 6 預覽版5終於跟大家見面了。我們現在正處於.NET 6 的後半部分,開始整合一些重要的功能。 例如.NET SDK 工作負載,它是我們.NET 統一願景的基礎,可以支援更多型別的應用程式。 與其他功能一樣,它也是為了更好地服務於端到端的使用者體驗。

您可以下載適用於Linux、macOS 和Windows 的.NET 6 預覽版5

請參閱ASP.NET CoreEF Core以及.NET MAUI,瞭解有關Web、資料訪問和跨平臺UI 方案新增功能的更多詳細資訊。

Visual Studio 2022 預覽版1 也在今天釋出,.NET 6 預覽版5包含其中。.NET 6 還在Visual Studio 16.11Visual 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 新增更多分析器

預設情況下,大多數新分析器應用在Info級別。您可以通過如下AnalysisMode的配置在Warning級別啟用這些分析器:

\<AnalysisMode\>AllEnabledByDefault\</AnalysisMode\>

我們釋出了我們想要的.NET 6 分析器集(加上一些額外的東西),然後將其中的大部分都公開了

預覽版5 中包含了Newell ClarkMeik Tranel的以下實現。請注意,社群使用者在之前的預覽版中貢獻了其他實現。

Contributor Issue Title
Newell Clark dotnet/runtime #33777 Use span-based string.Concat
Newell Clark dotnet/runtime #33784 Prefer string.AsSpan() over string.Substring() when parsing
Newell Clark dotnet/runtime #33789 Override Stream.ReadAsync/WriteAsync
Newell Clark dotnet/runtime #35343 Replace Dictionary<,>.Keys.Contains with ContainsKey
Newell Clark dotnet/runtime #45552 Use String.Equals instead of String.Compare
Meik Tranel dotnet/runtime #47180 Use String.Contains(char) instead of String.Contains(String)

.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 Forms: 預設字型

您現在可以使用Application.SetDefaultFont 為應用程式設定預設字型。 您使用的模式類似於設定high 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:

file

Chiller, 12pt:

file

.NET Core 3.0 中更新了預設字型。這一變化為一些使用者將.NET Framework 應用程式遷移到.NET Core 帶來了很大的阻礙。 預設字型設定使為應用程式選擇所需字型變得簡單,消除了遷移的障礙。

庫:放棄對舊框架的支援

從包中刪除框架是一個破壞原始碼的改動。但是,讓它一直支援我們釋出的所有框架也增加了包的複雜性和大小。過去,我們通過_harvesting_來解決這個問題,也就是:

  • 我們只為"當前"支援的框架做構建
  • 在構建期間,我們下載包的早期版本,並切除我們不再構建的早期框架的二進位制檔案

雖然這意味著您可以隨時更新而不必擔心我們會刪除框架,但這也意味著如果您使用切割過的二進位制檔案,您將永遠不會獲得任何錯誤修復或新功能。換句話說,切割過的無法提供服務的資產,現在已經被隱藏了,因為從您的角度來看,您可以繼續將包更新到更高版本,即使您正在使用我們不再更新的舊二進位制檔案。

從.NET 6 Preview 5 開始,我們計劃不再執行任何形式的harvesting,以確保我們為交付的所有內容都得到更好的服務。這意味著我們將放棄對任何早於以下版本的支援:

  • .NET Framework 4.6.1
  • .NET Core 3.1
  • .NET Standard 2.0

如果您當前正在引用來自早期框架的受影響的包,您將無法再將引用的包更新到更高版本。您可以將您的專案重新指向到更高版本的框架或選擇不更新引用的包(這通常不是一個大的回退,因為無論如何您已經在使用凍結的二進位制檔案)。

更多詳細資訊,包括受影響軟體包的完整列表,請參閱dotnet/announcement:刪除舊框架版本

庫:Microsoft.Extensions

我們一直在改進此版本的Microsoft.Extensions API。 在預覽版5 中,我們專注於託管和依賴注入。 在預覽版4 中,我們新增了一個用於日誌記錄的編譯時源生成器

感謝Martin Björkström](https://github.com/bjorkstromm) 的dotnet/runtime #51840 (AsyncServiceScope)

託管 – ConfigureHostOptions API

我們在IHostBuilder 上新增了一個新的ConfigureHostOptions API 以簡化應用程式配置(例如配置超時關閉):

using HostBuilder host = new()
    .ConfigureHostOptions(o =>
    {
        o.ShutdownTimeout = TimeSpan.FromMinutes(10);
    })
    .Build();

host.Run();

在預覽版5 之前,配置更加複雜一些:

using HostBuilder host = new()
    .ConfigureServices(services =>
    {
        services.Configure<HostOptions>(o =>
        {
            o.ShutdownTimeout = TimeSpan.FromMinutes(10);
        });
    })
    .Build();

host.Run();

依賴注入 – CreateAsyncScope API

您可能已經注意到,當服務提供者註冊了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;
}

您可以通過將返回的scope強制轉換為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 的使用
  • 允許相容trim的JSON 序列化

例如,原始碼生成器可以生成對properties更簡單有效的賦值/取值的程式碼,而不是在執行時通過Reflection.Emit生成get和set方法(這會用到私有記憶體並且影響啟動速度),使得效能得到了更大的提高。

您可以使用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
    {
    }
}

我們通過JsonSerializerOptionsAttribute 定義了一組JsonSerializer 功能,這些功能由提供最佳序列化吞吐量的原始碼生成模式提供。 這些功能可以提前指定給原始碼生成器,以避免在執行時進行額外檢查。 如果該屬性未宣告,執行時會使用預設的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&lt;T&gt; — 第二個使用更通用的無型別化實現,該實現執行型別測試以確定上下文例項中是否存在型別化實現。因此,它有點慢(由於型別測試)。如果給定型別沒有原始碼生成的實現,則序列化程式會丟擲NotSupportedException。但是它不會回退到基於反射的實現(我們的設計明確了這一點)。

基於Utf8JsonWriter的最快、最優化的原始碼生成模式目前僅可用於序列化。我們會根據您的反饋決定是否在未來提供基於Utf8JsonReader的反序列化實現。

但是,原始碼生成器還提供型別後設資料初始化邏輯,這也有助於反序列化。要使用預先生成的型別後設資料反序列化JsonMessage 的例項,您可以執行以下操作:

JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);

類似於上面的序列化,你也可以這樣寫:

JsonSerializer.Deserialize(json, typeof(JsonMessage), JsonContext.Default);

補充筆記

  • 可以通過派生的部分JsonSerializerContext 例項上的[JsonSerializable] 包含多種型別以用於源生成,不止支援一個。
  • 源生成器還支援巢狀物件和集合成員,而不僅僅是原始型別。

庫:WebSocket 壓縮

壓縮對於通過網路傳輸的任何資料都很重要。WebSockets 現在啟用壓縮。我們使用了WebSockets 的permessage-deflate 擴充套件實現,RFC 7692。它允許使用DEFLATE 演算法壓縮WebSockets 訊息有效負載。

此功能是使用者對GitHub 上Networking 的最高要求之一。您可以通過API 審查1API 審查2跟隨我們提供該API 的過程。

歸功於Ivan Zlatanov。謝謝Ivan!

我們意識到將壓縮與加密結合使用可能會導致攻擊,例如CRIMEBREACH。這意味著不能在單個壓縮上下文中將祕密與使用者生成的資料一起傳送,否則可以提取該祕密。為了讓使用者注意這些影響並幫助他們權衡風險,我們將API 重新命名為DangerousDeflateOptions。我們還新增了對特定訊息關閉壓縮的功能,因此如果使用者想要傳送祕密,他們可以在不壓縮的情況下安全地傳送。

Ivan還進行了一項後續工作,當禁用壓縮時,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);

歸功於Huo Yaoyuan。謝謝Huo!

庫:支援OpenTelemetry 指標

作為我們關注可觀察性的一部分,我們一直在為最近的幾個.NET 版本新增對OpenTelemetry 的支援。在.NET 6 中,我們新增了對OpenTelemetry Metrics API支援。通過新增對OpenTelemetry的支援,您的應用程式可以與其他OpenTelemetry 系統無縫互操作。

System.Diagnostics.MetricsOpenTelemetry Metrics API 規範的.NET 實現。Metrics API 是專門為處理原始測量而設計的,通常旨在高效且同時地生成這些測量的連續摘要。

API 包括可用於建立儀器物件(例如計數器)的Meter 類。API 公開了四個儀器類:Counter、Histogram、ObservableCounter 和ObservableGauge,以支援不同的指標場景。此外,API 公開MeterListener 類以允許偵聽儀器記錄的測量以進行聚合和分組。

OpenTelemetry .NET 實現將擴充套件為使用這些新API,這些API 增加了對Metrics 可觀察性場景的支援。

庫測量記錄示例

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% 的改進,如下圖所示。

file

歸功於Joseph Da Silva。 謝謝Joseph!

庫:Vector&lt;T&gt; 現在支援nint 和nuint

Vector&lt;T&gt; 現在支援在C# 9 中新增的nint 和nuint 基元型別。例如,此更改應該可以更輕鬆地使用具有指標或平臺相關長度的SIMD 指令。

庫:支援OpenSSL 3

.NET 加密API 支援使用OpenSSL 3作為Linux 上的首選本機加密提供程式。 如果可用,.NET 6 將使用OpenSSL 3。 否則,它將使用OpenSSL 1.x。

庫:新增支援ChaCha20/Poly1305 加密演算法

ChaCha20Poly1305 類已新增到System.Security.Cryptography。 要使用ChaCha20/Poly1305演算法,必須得到底層作業系統的支援。 靜態IsSupported 屬性可用於確定在給定上下文中是否支援該演算法。

  • Linux:需要OpenSSL 1.1 或更高版本。
  • Windows:構建20142 或更高版本(目前需要開發"內部人員"頻道)

感謝Kevin Jones對Linux 的支援。 謝謝Kevin!

互操作性: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 等功能。 它支援使用診斷工具,如dotnet-trace、dotnet-counters、dotnet-stacks,用於在移動裝置(iOS/Android) 和桌面上執行的應用程式。

這些新功能開啟了在PrefView/SpeedScope/Chromium、dotnet-trace等工具中分析MonoVM 生成的nettrace 檔案的能力,或使用TraceEvent等庫編寫自定義解析器

我們將繼續包含更多功能,主要側重於SDK 整合並將更多本地執行時事件(Microsoft-Windows-DotNETRuntime) 適配到MonoVM 中,從而在nettrace 檔案中啟用更多事件。

現已具備以下功能:

  • 在MonoVM 和CoreCLR 之間共享本機EventPipe/DiagnosticsServer 庫
  • 將TCP/IP 支援新增到DiagnosticsServer 並利用該配置構建MonoVM iOS/Android 執行時包。需要以支援移動平臺。
  • BCL EventSources 在MonoVM 上執行,將事件傳送到EventPipe。
  • System.Diagnostics.Tracing.RuntimeEventSource 發出的BCL 執行時計數器連線到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 取樣會話的一部分。

file

Android CPU 取樣(PerfView)

下圖演示了在PerfView(無限睡眠中的主執行緒)中檢視的Android CPU 取樣。
file

執行時:CodeGen

RyuJIT 中進行了以下更改。

社群貢獻

感謝@SingleAccretion的這些貢獻。

動態PGO

file

JIT 迴圈優化

LSRA

在"分配暫存器"表中包含暫存器選擇啟發式https://github.com/dotnet/runtime/pull/52513新舊錶的差異:

file

保持結構在註冊

優化除錯經驗

file

SIMD

涉及SIMD 或HWIintrinsics 的某些方法的內聯現在應該具有改進的程式碼生成和效能。 我們看到了高達95% 的改進

file

結束

就功能的廣度和數量而言,.NET 6 預覽版5 可能是迄今為止最大的預覽版。 您可以使用源生成器和分析器檢視Roslyn 功能對低階庫功能的影響程度。 未來真的到來了。 我們現在擁有一個非常強大的編譯器工具鏈,使我們能夠生成高度優化和正確的程式碼,併為您自己的專案提供完全相同的體驗。

現在是開始測試.NET 6 的好時機。現在我們根據您的反饋採取行動還為時過早。 很難想象,雖然我們要到2021 年11 月才會釋出,但反饋視窗很快就會縮小到僅針對高嚴重性問題。 該團隊提前進行了大約一年半的預覽,並將很快轉向主要關注質量問題。 如果可以,請嘗試.NET 6。

感謝您成為.NET 開發人員。

相關文章