產業新聞

.NET 11預覽3:開發者評測

.NET 11在距離計劃的2026年11月GA約六個月達到其第三次預覽版本,不同於主要是基礎建設的預覽1和2,預覽3是您能夠真正感受到發行形狀的一個版本。

運行時異步不再是一個"預覽功能門檻"實驗,JIT獲得了另一批免費的優化,ASP.NET Core自帶Zstandard,以及C# 15的聯合類型——人們詢問了近十年的語言特性。

這不是LTS版本,.NET 11是下一個標準支持版本,擁有24個月的支持,這已經改變了升級與否的計算。 以下是值得作為開發者關注的內容,以及仍然存在的粗糙邊緣。

C# 15聯合類型:重頭戲

如果您一直在編寫OneOf<T1, T2>庫、手動創建封閉記錄層次結構或只是羨慕 F#開發者,這就是頭條。C# 15 引入了一個聯合關鍵字,該關鍵字聲明一個值恰好是一個固定類型集中的一個,具有編譯器強制的完整性。 聯合類型在預覽2中出現; 預覽3改善了對其的IDE支持。

C#團隊的方法更接近於類型聯合,而不是F#區分聯合:成員類型是您單獨定義的現有類型,而不是嵌套在聯合聲明內的標籤案例。 聯合基本上是一個包裝對象並限制其內容的結構。 從調用現場來看,它感覺是原生的——從成員類型到聯合類型的隱式轉換,覆蓋Pet.Value的完整切換表達式,當編譯器能夠看到所有情況時不需要默認分支。

[Union]
public partial struct Pet : IUnion
{
    public Pet(Dog dog);
    public Pet(Cat cat);
    public Pet(Bird bird);
}

string Describe(Pet pet) => pet.Value switch
{
    Dog d  => $"Dog named {d.Name}",
    Cat c  => $"Cat ({c.Color})",
    Bird b => $"Bird, {b.Species}",
    // no default - compiler knows the set is closed
};
[Union]
public partial struct Pet : IUnion
{
    public Pet(Dog dog);
    public Pet(Cat cat);
    public Pet(Bird bird);
}

string Describe(Pet pet) => pet.Value switch
{
    Dog d  => $"Dog named {d.Name}",
    Cat c  => $"Cat ({c.Color})",
    Bird b => $"Bird, {b.Species}",
    // no default - compiler knows the set is closed
};
<Union>
Public Partial Structure Pet
    Implements IUnion

    Public Sub New(dog As Dog)
    End Sub

    Public Sub New(cat As Cat)
    End Sub

    Public Sub New(bird As Bird)
    End Sub
End Structure

Function Describe(pet As Pet) As String
    Return pet.Value Select Case
        Case d As Dog
            Return $"Dog named {d.Name}"
        Case c As Cat
            Return $"Cat ({c.Color})"
        Case b As Bird
            Return $"Bird, {b.Species}"
        ' no default - compiler knows the set is closed
    End Select
End Function
$vbLabelText   $csharpLabel

優勢是真實的:封閉類型、無無效狀態、編譯時而非NotImplementedExceptionat凌晨3點的完整性。 將鯊魚添加到聯合中,每次覆蓋Pet的切換都會亮起警告,直到您處理它。

缺點也是真實的,值得在任何誠實的評論中標記。 暴露的對象值屬性是一個氣味——目前有關在更類型安全的東西後隱藏它的GitHub討論。 公共構造函數隱式地定義了聯合接受哪些類型,這既不可發現也不明確。 F#互操作未解決(這兩個模型在根本上是不同的)。 更廣泛的完整性故事仍然有差距:閉合層次結構和閉合枚舉,兩個會完成這幅畫面的提案,仍然是提案。 僅僅是聯合是很棒的。 聯合加上閉合枚舉加上閉合層次結構將是一次世代的轉變。 我們還沒有完全達到那個。

運行時異步V2和JIT改進

運行時異步是 .NET 安靜地重寫了異步/等待實際執行方式。 而不是C#編譯器為每個異步方法發出一個狀態機類,運行時本身管理暫停和恢復。 顯而易見的回報:更乾淨的堆棧跟踪、更小的分配和不需要您滾動過MoveNext框架以找到您自己代碼的調試器。

在預覽3中,運行時異步取消了EnablePreviewFeatures要求。 您仍然需要切換功能開關 - <Features>runtime-async=on</Features> - 但不再需要將每個API調用選擇到預覽範疇。 NativeAOT和ReadyToRun支持也在此預覽中登陸,這縮小了JIT和AOT場景之間的差距。 持續對象被更積極地重用,並且尚未更改的局部變量在暫停期間不保存。 在異步密集的代碼路徑中——如Kestrel管道或EF Core查詢工作器——這是分配壓力方面有意義的下降。

JIT獲得了通常的批次"您現有的代碼現在更快,不做任何事情":

  • 多目標切換表達式,如 x 是 0或1或2或3或4 現在融合成無分支檢查。
  • 值[^1] + 值[^2] 模式的邊界檢查被更積極地消除,循環中常見的i + cns < len 情況乾淨地崩潰。
  • 無符號整數轉浮點數和無符號整數轉雙精度浮點數在預AVX-512 x86硬件上更快——有些小眾,但如果您攜帶舊機盒,它們是真實存在的。

WebAssembly用戶直接在運行時獲得WebCIL載荷加載、更好的調試符號,以及float[] / Span<float> / ArraySegment<float> 無來回開銷的編排。 這些單獨看並不戲劇性,但它們一起是那種複合工作,使得Blazor WASM感覺不再像折衷方案。

問題是硬件底線。 .NET 11提高了對x86/x64和Arm64的最低指令集要求。Apple Silicon和大多數Linux SBC都沒問題 - Arm64上的ReadyToRun目標只是增加了LSE - 但非常古老的x86硬件不在其中。 在您假設實地升級之前,審核您的設備。

ASP.NET Core和Blazor

Zstandard是此處的頭條。 ASP.NET Core 現在支持zstd進行響應壓縮和請求解壓縮,當您添加中間件時默認啟用。 配置呈現您期望的形狀:

builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions { Quality = 6 };
});
builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions { Quality = 6 };
});
Imports Microsoft.Extensions.DependencyInjection

builder.Services.AddResponseCompression()
builder.Services.AddRequestDecompression()
builder.Services.Configure(Of ZstandardCompressionProviderOptions)(Sub(options)
    options.CompressionOptions = New ZstandardCompressionOptions With {.Quality = 6}
End Sub)
$vbLabelText   $csharpLabel

對於提供JSON或文本載荷給已經會說zstd的客戶端的 API - 在移動和gRPC關聯生態系統中越來越普遍 - 這是一種可測量的帶寬增益,不依賴於第三方庫。 值得注意的是,這也是社區貢獻,而不是微軟內部貢獻,這是一個健康的信號。

Blazor 的Virtualize<TItem>最終停止假設每行都是相同的高度。 這是一個長期困擾的問題:任何有變量內容的列表 - 評論、聊天信息、任何包含包裝文本的內容 - 需要手工處理。 現在,組件在運行時測量項目。預覽3版本還修復了一堆Blazor錯誤:在ResourceCollectionProvider漏洞。 單獨看是小問題,合併看是清理信號,顯示框架正從"每次發行新東西"階段成長。

Kestrel 也開始處理HTTP/3請求而不等待控制流和SETTINGS框架,這降低了新連接上的首次請求延遲。 如果您測量過HTTP/3 P99並看到奇怪的冷啟動尾巴,這就是您的解決方案。

.NET MAUI

預覽3中的MAUI主要是縮小讓它感覺像個測試版本太久的差距。 Map控件獲得引針集群、自定義引針圖標、自定義JSON樣式、以及圓圈、多邊形和折線的點擊事件——所有這些都是實際生產地圖UI需要的東西,以前每個平台都需要自定義處理程序。 內置的長按手勢識別器現在可以使用了,不需要自定義。 默認打開的隱式XAML命名空間聲明,這減少了在每個文件頂部的樣板代碼。

平台平價獲得提升:Permissions.PostNotifications現在在iOS上實現(以前只支持Android),Android獲得對Android 17和API級別37的預覽支持。

誠實的評估:這是穩定、明智的迭代,而不是重塑。 2026年的MAUI比2023年的MAUI好得多,但如果您較早之前放棄了它,僅憑預覽3還不會將您拉回。 如果您已經在使用MAUI,這些正是您想要的QoL更改。

SDK、CLI和.NET watch

這是小東西累加的部分。有幾個我認為真正改變日常工作流的:

.NET sln現在可以直接從CLI創建和編輯解決方案過濾器(.slnf)。 對於單一代碼庫和大型微軟風格的解決方案,打開一個200個項目的SLN來處理其中的三個一直是一個真正的成本。現在您可以從終端進行範圍限定:

dotnet new slnf --name MyApp.slnf
dotnet sln MyApp.slnf add src/Lib/Lib.csproj
dotnet new slnf --name MyApp.slnf
dotnet sln MyApp.slnf add src/Lib/Lib.csproj
SHELL

基於文件的應用程序(.NET run app.cs工作流)終於支持#:include,這意味著C#腳本可以將助手拆分成單獨的文件。 結合Roslyn中指令的編輯器完成,這推動了基於文件的應用程序從"玩具"到"真正的自動化工具的可行"範圍——權力殼和小型Python腳本擁有多年。

.NET run -e FOO=BAR允許您在命令行傳遞環境變量,而不需要出口shell狀態或編輯啟動配置文件。 微小,但如果您曾經開過三個終端,有不同的ASPNETCORE_ENVIRONMENT值,您知道這種痛苦。

.NET watch整合了Aspire應用主機,在下一次文件更改後自動重啟並更優雅地處理WinForms和WPF的Ctrl+C(一個永恆的小創面)。 .NET format接受--framework用於多目標化項目。 .NET test在MTP模式下支持--artifacts-path。 而.NET tool exec / dnx不再要求額外的批准,這對於一次性工具運行來說是一個摩擦點。

痛點

平衡的評論需要考慮粗糙的邊緣,而預覽3確實有它們。

工具故事是粗糙的。 Visual Studio 2026在.NET 10推出六個月後仍然是預覽版本,並且微軟託管的生成代理尚未穩定支持VS 2026。 在 .NET 10 SDK 補丁版本中更改需要MSBuild 18(VS 2026),這違反了微軟宣傳的semver保證。 任何在微軟託管代理上運行CI的人都有必要要么固定SDK 10.0.4,要么切換到預覽生成圖像。 如果您考慮將CI管道移至 .NET 11 預覽版本,請預期相似 - 團隊自身承認,預覽 SDK在10.0.2和10.0.3中破壞了一些東西,然後才穩定下來。

運行時異步仍然是選擇性啟用的。 即使預覽功能門檻已消失,您仍需啟用runtime-async=on。 對於綠地代碼來說,這很好; 對於在NuGet上發佈的庫,您仍然無法假設您的用戶啟用了開關,因此實際好處被推遲直到該功能默認啟用(不包括在.NET 11中)。

硬件要求上升。 最低x86/x64指令集要求上升。大多數團隊不會注意到。有些會——如果他們不先進行審核,他們會在部署時發現。

STS,而不是LTS。 .NET 11獲得24個月的支持。 .NET 10(當前LTS)獲得36個月。 對於升級節奏緩慢的商店來說,.NET 10仍然是更保守的選擇,採用.NET 11意味著承諾2028年的另一次升級。採用STS的原因是功能; 反對的理由是日曆。

預覽就是預覽。 這不是穩定性抱怨 - 微軟的預覽過程很好 - 但預覽3不是候選發行版本。 生產部署至少要等到RC1。內部工具、副專案和探索是現在的合適范圍。

結論

如果您每天都寫C#,值得在本週安裝和試用.NET 11 預覽版 3,特別是接觸聯合類型,這是多年的語言特性變化中最有意義的。 如果您維護庫,JIT和運行時異步工作意味著您的代碼在 .NET 11 上會更快,並且不需要編輯,這是最好的升級。 如果您發佈 MAUI 應用,地圖和手勢工作是真正的進步。

如果您運行生產 .NET 工作負載,答案是無聊的:繼續計劃,繼續觀察並標記11月的 GA。 令人興奮的部分正在著陸,但工具鏈——VS、生成代理和SDK補丁節奏——是摩擦實際存在的地方,尚未得到解決。

| --- |

來源.NET Blog公告What's new in .NET 11 (Microsoft Learn)運行時版本說明ASP.NET Core版本說明SDK版本說明探索C# 15的聯合類型