日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.NET 6 攻略大全(三)

發(fā)布時間:2023/12/4 asp.net 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET 6 攻略大全(三) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方藍(lán)字

關(guān)注我們

(本文閱讀時間:15分鐘)

.NET 6 繼續(xù)與大家相約周日啦。本篇文章將介紹:單文件應(yīng)用、IL 修整、System.Text.Json、源代碼構(gòu)建、庫AIP的相關(guān)攻略。?

單文件應(yīng)用?

在 .NET 6中,已為 Windows 和 macOS 啟用內(nèi)存中單文件應(yīng)用程序。在 .NET 5 中,這種部署類型僅限于 Linux。您現(xiàn)在可以為所有受支持的操作系統(tǒng)發(fā)布作為單個文件部署和啟動的單文件二進(jìn)制文件。單文件應(yīng)用不再將任何核心運行時程序集提取到臨時目錄。

這種擴展功能基于稱為“超級主機”的構(gòu)建塊。“apphost” 是在非單文件情況下啟動應(yīng)用程序的可執(zhí)行文件,例如 myapp.exe或./myapp. Apphost 包含用于查找運行時、加載它并使用該運行時啟動您的應(yīng)用程序的代碼。Superhost 仍然執(zhí)行其中一些任務(wù),但使用所有 CoreCLR 本機二進(jìn)制文件的靜態(tài)鏈接副本。靜態(tài)鏈接是我們用來實現(xiàn)單一文件體驗的方法。本機依賴項(如 NuGet 包附帶的)是單文件嵌入的顯著例外。默認(rèn)情況下,它們不包含在單個文件中。例如,WPF 本機依賴項不是超級主機的一部分,因此會在單文件應(yīng)用程序之外產(chǎn)生其他文件。您可以使用該設(shè)置 IncludeNativeLibrariesForSelfExtract 嵌入和提取本機依賴項。

▌靜態(tài)分析

我們改進(jìn)了單文件分析器以允許自定義警告。如果您的 API 在單文件發(fā)布中不起作用,您現(xiàn)在可以使用[RequiresAssemblyFiles]屬性對其進(jìn)行標(biāo)記,如果啟用了分析器,則會出現(xiàn)警告。添加該屬性還將使方法中與單個文件相關(guān)的所有警告靜音,因此您可以使用該警告將警告向上傳播到您的公共 API。

當(dāng) PublishSingleFile 設(shè)置為 true 時,會自動為 exe 項目啟用單文件分析器,但您也可以通過將 EnableSingleFileAnalysis 設(shè)置為 true 來為任何項目啟用它。如果您想支持將庫作為單個文件應(yīng)用程序的一部分,這將很有幫助。

在 .NET 5 中,我們?yōu)閱挝募行袨椴煌?Assembly.Location 和一些其他 API 添加了警告。

▌壓縮

單文件包現(xiàn)在支持壓縮,可以通過將屬性設(shè)置 EnableCompressionInSingleFile為true. 在運行時,文件會根據(jù)需要解壓縮到內(nèi)存中。壓縮可以為某些場景節(jié)省大量空間。

讓我們看一下與 NuGet 包資源管理器一起使用的單個文件發(fā)布(帶壓縮和不帶壓縮)。

無壓縮:172 MB

壓縮:71.6 MB

壓縮會顯著增加應(yīng)用程序的啟動時間,尤其是在 Unix 平臺上。Unix 平臺有一個不能用于壓縮的無拷貝快速啟動路徑。您應(yīng)該在啟用壓縮后測試您的應(yīng)用程序,看看額外的啟動成本是否可以接受。

▌單文件調(diào)試

目前只能使用平臺調(diào)試器(如 WinDBG)來調(diào)試單文件應(yīng)用程序。我們正在考慮使用更高版本的 Visual Studio 2022 添加 Visual Studio 調(diào)試。

▌macOS 上的單文件簽名

單文件應(yīng)用程序現(xiàn)在滿足 macOS 上的 Apple 公證和簽名要求。具體更改與我們根據(jù)離散文件布局構(gòu)建單文件應(yīng)用程序的方式有關(guān)。

Apple 開始對macOS Catalina實施新的簽名和公證要求。我們一直在與 Apple 密切合作,以了解需求,并尋找使 .NET 等開發(fā)平臺能夠在該環(huán)境中正常工作的解決方案。我們已經(jīng)進(jìn)行了產(chǎn)品更改并記錄了用戶工作流程,以滿足 Apple 在最近幾個 .NET 版本中的要求。剩下的差距之一是單文件簽名,這是在 macOS 上分發(fā) .NET 應(yīng)用程序的要求,包括在 macOS 商店中。

IL 修整

該團隊一直致力于為多個版本進(jìn)行 IL 修整。.NET 6 代表了這一旅程向前邁出的重要一步。我們一直在努力使更激進(jìn)的修剪模式安全且可預(yù)測,因此有信心將其設(shè)為默認(rèn)模式。TrimMode=link 以前是可選功能,現(xiàn)在是默認(rèn)功能。

我們有一個三管齊下的修剪策略:

  • 提高平臺的修剪能力。

  • 對平臺進(jìn)行注釋以提供更好的警告并使其他人也能這樣做。

  • 在此基礎(chǔ)上,讓默認(rèn)的修剪模式更具侵略性,以便讓應(yīng)用程序變小。

由于使用未注釋反射的應(yīng)用程序的結(jié)果不可靠,修剪之前一直處于預(yù)覽狀態(tài)。有了修剪警告,體驗現(xiàn)在應(yīng)該是可預(yù)測的。沒有修剪警告的應(yīng)用程序應(yīng)該正確修剪并且在運行時觀察到行為沒有變化。目前,只有核心的 .NET 庫已經(jīng)完全注解了修剪,但我們希望看到生態(tài)系統(tǒng)注釋修剪并兼容修剪。

▌減小應(yīng)用程序大小

讓我們使用SDK 工具之一的crossgen來看看這個修剪改進(jìn)。它可以通過幾個修剪警告進(jìn)行修剪,crossgen 團隊能夠解決。

首先,讓我們看一下將 crossgen 發(fā)布為一個獨立的應(yīng)用程序而無需修剪。它是 80 MB(包括 .NET 運行時和所有庫)。

然后我們可以嘗試(現(xiàn)在是舊版).NET 5 默認(rèn)修剪模式,copyused. 結(jié)果降至 55 MB。

新的 .NET 6 默認(rèn)修剪模式link將獨立文件大小進(jìn)一步降低到 36MB。

我們希望新的link修剪模式能更好地與修剪的期望保持一致:顯著節(jié)省和可預(yù)測的結(jié)果。

默認(rèn)啟用警告

修剪警告告訴您修剪可能會刪除運行時使用的代碼的地方。這些警告以前默認(rèn)禁用,因為警告非常嘈雜,主要是由于 .NET 平臺沒有參與修剪作為第一類場景。

我們對大部分 .NET 庫進(jìn)行了注釋,以便它們產(chǎn)生準(zhǔn)確的修剪警告。因此,我們覺得是時候默認(rèn)啟用修剪警告了。ASP.NET Core 和 Windows 桌面運行時庫尚未注釋。我們計劃接下來注釋 ASP.NET 服務(wù)組件(在 .NET 6 之后)。我們希望看到社區(qū)在 .NET 6 發(fā)布后對 NuGet 庫進(jìn)行注釋。

您可以通過設(shè)置<SuppressTrimAnalysisWarnings>為true來禁用警告。

更多信息:

  • 修剪警告

  • 修剪介紹

  • 準(zhǔn)備 .NET 庫以進(jìn)行修剪

與本機 AOT 共享

我們也為Native AOT 實驗實現(xiàn)了相同的修剪警告,這應(yīng)該會以幾乎相同的方式改善 Native AOT 編譯體驗。

數(shù)學(xué)

我們顯著改進(jìn)了數(shù)學(xué) API。社區(qū)中的一些人已經(jīng)在享受這些改進(jìn)。

面向性能的 API

System.Math 中添加了面向性能的數(shù)學(xué) API。如果底層硬件支持,它們的實現(xiàn)是硬件加速的。

新 API:

  • SinCos 用于同時計算 Sin 和 Cos。

  • ReciprocalEstimate 用于計算 1 / x的近似值。

  • ReciprocalSqrtEstimate 用于計算1 / Sqrt(x) 的近似值。

新的重載:

  • Clamp,DivRem,Min 和 Max 支持 nint 和 nuint。

  • Abs 和 Sign支持 nint。

  • DivRem 變體返回 tuple。

性能改進(jìn):

ScaleB被移植到 C# 導(dǎo)致調(diào)用速度提高了 93%。感謝亞歷克斯·科文頓。

大整數(shù)性能

改進(jìn)了從十進(jìn)制和十六進(jìn)制字符串中解析 BigIntegers 。我們看到了高達(dá) 89% 的改進(jìn),如下圖所示(越低越好)。

感謝約瑟夫·達(dá)席爾瓦。

▌ComplexAPI 現(xiàn)在注釋為 readonly

現(xiàn)在對各種 API 進(jìn)行了注釋,System.Numerics.Complexreadonly 以確保不會對readonly值或傳遞的值進(jìn)行復(fù)制 in。

歸功于 hrrrrustic 。

▌BitConverter現(xiàn)在支持浮點到無符號整數(shù)位廣播

BitConverter 現(xiàn)在支持 DoubleToUInt64Bits, HalfToUInt16Bits, SingleToUInt32Bits, UInt16BitsToHalf, UInt32BitsToSingle, 和UInt64BitsToDouble. 這應(yīng)該使得在需要時更容易進(jìn)行浮點位操作。

歸功于 Michal Petryka 。

▌BitOperations支持附加功能

BitOperations現(xiàn)在支持IsPow2,RoundUpToPowerOf2和提供nint/nuint重載現(xiàn)有函數(shù)。

感謝約翰凱利、霍耀源和羅賓林德納。

▌Vector<T>, Vector2, Vector3, 和Vector4改進(jìn)

Vector<T> 現(xiàn)在支持C# 9 中添加的原始類型nint和nuint原始類型。例如,此更改應(yīng)該可以更簡單地使用帶有指針或平臺相關(guān)長度類型的 SIMD 指令。

Vector<T> 現(xiàn)在支持一種Sum方法來簡化計算向量中所有元素的“水平和”的需要。歸功于伊萬茲拉塔諾夫。

Vector<T> 現(xiàn)在支持一種通用方法As<TFrom, TTo>來簡化在具體類型未知的通用上下文中處理向量。感謝霍耀源

重載支持Span<T>已添加到Vector2、Vector3和Vector4以改善需要加載或存儲矢量類型時的體驗。

▌更好地解析標(biāo)準(zhǔn)數(shù)字格式

我們改進(jìn)了標(biāo)準(zhǔn)數(shù)字類型的解析器,特別是.ToString和.TryFormatParse。他們現(xiàn)在將理解對精度 > 99 位小數(shù)的要求,并將為那么多位數(shù)提供準(zhǔn)確的結(jié)果。此外,解析器現(xiàn)在更好地支持方法中的尾隨零。

以下示例演示了之前和之后的行為。

  • 32.ToString("C100")->C132

  • .NET 6:$32.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

  • .NET 5:我們在格式化代碼中人為限制只能處理 <= 99 的精度。對于精度 >= 100,我們改為將輸入解釋為自定義格式。

  • 32.ToString("H99")-> 扔一個FormatException

  • .NET 6:拋出 FormatException。

  • 這是正確的行為,但在這里調(diào)用它是為了與下一個示例進(jìn)行對比。

  • 32.ToString("H100")->H132

  • .NET 6:拋出 FormatException。

  • .NET 5:H是無效的格式說明符。所以,我們應(yīng)該拋出一個FormatException. 相反,我們將精度 >= 100 解釋為自定義格式的錯誤行為意味著我們返回了錯誤的值。

  • double.Parse("9007199254740997.0")->9007199254740998

  • .NET 6 9007199254740996:。

  • .NET 5:9007199254740997.0不能完全以 IEEE 754 格式表示。使用我們當(dāng)前的舍入方案,正確的返回值應(yīng)該是9007199254740996. 但是,輸入的最后一部分迫使解析器錯誤地舍入結(jié)果并返回 .09007199254740998。

System.Text.Json

System.Text.Json 提供多種高性能 API 用于處理 JSON 文檔。在過去的幾個版本中,我們添加了新功能,以進(jìn)一步提高 JSON 處理性能并減輕對希望從NewtonSoft.Json遷移的人的阻礙。此版本包括在該路徑上的繼續(xù),并且在性能方面向前邁出了一大步,特別是在序列化程序源生成器方面。

▌JsonSerializer 源生成

注意:使用 .NET 6 RC1 或更早版本的源代碼生成的應(yīng)用程序應(yīng)重新編譯。

幾乎所有 .NET 序列化程序的支柱都是反射。反射對于某些場景來說是一種很好的能力,但不能作為高性能云原生應(yīng)用程序(通常(反)序列化和處理大量 JSON 文檔)的基礎(chǔ)。反射是啟動、內(nèi)存使用和程序集修整的問題。

運行時反射的替代方法是編譯時源代碼生成。在 .NET 6 中,我們包含一個新的源代碼生成器作為System.Text.Json. JSON 源代碼生成器可以與多種方式結(jié)合使用JsonSerializer并且可以通過多種方式進(jìn)行配置。

它可以提供以下好處:

? 減少啟動時間

? 提高序列化吞吐量

? 減少私有內(nèi)存使用

? 刪除運行時使用System.Reflection 和System.Reflection.Emit

? IL 修整兼容性

默認(rèn)情況下,JSON 源生成器為給定的可序列化類型發(fā)出序列化邏輯。JsonSerializer通過生成直接使用的源代碼,這提供了比使用現(xiàn)有方法更高的性能Utf8JsonWriter。簡而言之,源代碼生成器提供了一種在編譯時為您提供不同實現(xiàn)的方法,以使運行時體驗更好。

給定一個簡單的類型:

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{} }

使用此模式的序列化程序調(diào)用可能類似于以下示例。此示例提供了可能的最佳性能。

using MemoryStream ms = new(); using Utf8JsonWriter writer = new(ms);JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage); writer.Flush();// Writer contains: // {"Message":"Hello, world!"}

最快和最優(yōu)化的源代碼生成模式——基于Utf8JsonWriter——目前僅可用于序列化。Utf8JsonReader根據(jù)您的反饋,將來可能會提供對反序列化的類似支持。

源生成器還發(fā)出類型元數(shù)據(jù)初始化邏輯,這也有利于反序列化。JsonMessage要反序列化使用預(yù)生成類型元數(shù)據(jù)的實例,您可以執(zhí)行以下操作:

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

▌JsonSerializer 支持 IAsyncEnumerable

您現(xiàn)在可以使用System.Text.Json (反)序列化IAsyncEnumerable<T>JSON數(shù)組。以下示例使用流作為任何異步數(shù)據(jù)源的表示。源可以是本地計算機上的文件,也可以是數(shù)據(jù)庫查詢或 Web 服務(wù) API 調(diào)用的結(jié)果。

JsonSerializer.SerializeAsync已更新以識別并為IAsyncEnumerable值提供特殊處理。

using System; using System.Collections.Generic; using System.IO; using System.Text.Json;static async IAsyncEnumerable<int> PrintNumbers(int n) {for (int i = 0; i < n; i++) yield return i; }using Stream stream = Console.OpenStandardOutput(); var data = new { Data = PrintNumbers(3) }; await JsonSerializer.SerializeAsync(stream, data); // prints {"Data":[0,1,2]}

IAsyncEnumerable 僅使用異步序列化方法支持值。嘗試使用同步方法進(jìn)行序列化將導(dǎo)致NotSupportedException被拋出。

流式反序列化需要一個新的 API 來返回 I AsyncEnumerable<T>. 我們?yōu)榇颂砑恿薐sonSerializer.DeserializeAsyncEnumerable方法,您可以在以下示例中看到。

using System; using System.IO; using System.Text; using System.Text.Json;var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]")); await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream)) {Console.WriteLine(item); }

此示例將按需反序列化元素,并且在使用特別大的數(shù)據(jù)流時非常有用。它僅支持從根級 JSON 數(shù)組讀取,盡管將來可能會根據(jù)反饋放寬。

現(xiàn)有 DeserializeAsync 方法名義上支持 I AsyncEnumerable<T>,但在其非流方法簽名的范圍內(nèi)。它必須將最終結(jié)果作為單個值返回,如以下示例所示。

using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Text.Json;var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}")); var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream); await foreach (int item in result.Data) {Console.WriteLine(item); }public class MyPoco {public IAsyncEnumerable<int> Data { get; set; } }

在此示例中,反序列化器將 IAsyncEnumerable 在返回反序列化對象之前緩沖內(nèi)存中的所有內(nèi)容。這是因為反序列化器需要在返回結(jié)果之前消耗整個 JSON 值。

▌System.Text.Json:可寫 DOM 功能

可寫 JSON DOM特性為 System.Text.Json添加了一個新的簡單且高性能的編程模型。這個新的 API 很有吸引力,因為它避免了需要強類型的序列化合約,并且與現(xiàn)有的 JsonDocument類型相比,DOM 是可變的。

這個新的 API 有以下好處:

  • 在使用POCO類型是不可能或不希望的情況下,或者當(dāng) JSON 模式不固定且必須檢查的情況下,序列化的輕量級替代方案。

  • 啟用對大樹子集的有效修改。例如,可以有效地導(dǎo)航到大型 JSON 樹的子部分并從該子部分讀取數(shù)組或反序列化 POCO。LINQ 也可以與它一起使用。

以下示例演示了新的編程模型。

// Parse a JSON objectJsonNode jNode = JsonNode.Parse("{"MyProperty":42}");int value = (int)jNode["MyProperty"];Debug.Assert(value == 42);// orvalue = jNode["MyProperty"].GetValue<int>();Debug.Assert(value == 42);// Parse a JSON arrayjNode = JsonNode.Parse("[10,11,12]");value = (int)jNode[1];Debug.Assert(value == 11);// orvalue = jNode[1].GetValue<int>();Debug.Assert(value == 11);// Create a new JsonObject using object initializers and array paramsvar jObject = new JsonObject{["MyChildObject"] = new JsonObject{["MyProperty"] = "Hello",["MyArray"] = new JsonArray(10, 11, 12)}};// Obtain the JSON from the new JsonObjectstring json = jObject.ToJsonString();Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}// Indexers for property names and array elements are supported and can be chained Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>()?==?11);

▌ReferenceHandler.IgnoreCycles

JsonSerializer(System.Text.Json)現(xiàn)在支持在序列化對象圖時忽略循環(huán)的能力。該ReferenceHandler.IgnoreCycles選項具有與 Newtonsoft.Json ReferenceLoopHandling.Ignore類似的行為。一個關(guān)鍵區(qū)別是 System.Text.Json 實現(xiàn)用null JSON 標(biāo)記替換引用循環(huán),而不是忽略對象引用。

您可以在以下示例中看到ReferenceHandler.IgnoreCycles 的行為。在這種情況下,該Next屬性被序列化為null,因為否則它會創(chuàng)建一個循環(huán)。

class Node {public string Description { get; set; }public object Next { get; set; } }void Test() {var node = new Node { Description = "Node 1" };node.Next = node;var opts = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles };string json = JsonSerializer.Serialize(node, opts);Console.WriteLine(json); // Prints {"Description":"Node 1","Next":null} }

源代碼構(gòu)建

通過源代碼構(gòu)建,您只需幾個命令即可在您自己的計算機上從源代碼構(gòu)建 .NET SDK 。讓我解釋一下為什么這個項目很重要。

源代碼構(gòu)建是一個場景,也是我們在發(fā)布 .NET Core 1.0 之前一直與 Red Hat 合作開發(fā)的基礎(chǔ)架構(gòu)。幾年后,我們非常接近于交付它的全自動版本。對于 Red Hat Enterprise Linux (RHEL) .NET 用戶來說,這個功能很重要。Red Hat 告訴我們,.NET 已經(jīng)發(fā)展成為其生態(tài)系統(tǒng)的重要開發(fā)者平臺。好的!

Linux 發(fā)行版的黃金標(biāo)準(zhǔn)是使用作為發(fā)行版存檔一部分的編譯器和工具鏈構(gòu)建開源代碼。這適用于 .NET 運行時(用 C++ 編寫),但不適用于任何用 C# 編寫的代碼。對于 C# 代碼,我們使用兩遍構(gòu)建機制來滿足發(fā)行版要求。這有點復(fù)雜,但了解流程很重要。

Red Hat 使用 .NET SDK (#1) 的 Microsoft 二進(jìn)制構(gòu)建來構(gòu)建 .NET SDK 源代碼,以生成 SDK (#2) 的純開源二進(jìn)制構(gòu)建。之后,使用這個新版本的 SDK (#2) 再次構(gòu)建相同的 SDK 源代碼,以生成可證明的開源 SDK (#3)。.NET SDK (#3) 的最終二進(jìn)制版本隨后可供 RHEL 用戶使用。之后,Red Hat 可以使用相同的 SDK (#3) 來構(gòu)建新的 .NET 版本,而不再需要使用 Microsoft SDK 來構(gòu)建每月更新。

這個過程可能令人驚訝和困惑。開源發(fā)行版需要通過開源工具構(gòu)建。此模式確保不需要 Microsoft 構(gòu)建的 SDK,無論是有意還是無意。作為開發(fā)者平臺,包含在發(fā)行版中的門檻比僅使用兼容許可證的門檻更高。源代碼構(gòu)建項目使 .NET 能夠滿足該標(biāo)準(zhǔn)。

源代碼構(gòu)建的可交付成果是源代碼壓縮包。源 tarball 包含 SDK 的所有源(對于給定版本)。從那里,紅帽(或其他組織)可以構(gòu)建自己的 SDK 版本。Red Hat 政策要求使用內(nèi)置源工具鏈來生成二進(jìn)制 tar 球,這就是他們使用兩遍方法的原因。但是源代碼構(gòu)建本身不需要這種兩遍方法。

在 Linux 生態(tài)系統(tǒng)中,給定組件同時擁有源和二進(jìn)制包或 tarball 是很常見的。我們已經(jīng)有了可用的二進(jìn)制 tarball,現(xiàn)在也有了源 tarball。這使得 .NET 與標(biāo)準(zhǔn)組件模式相匹配。

.NET 6 的重大改進(jìn)是源 tarball 現(xiàn)在是我們構(gòu)建的產(chǎn)品。它過去需要大量的人工來制作,這也導(dǎo)致將源 tarball 交付給 Red Hat 的延遲很長。雙方都對此不滿意。

在這個項目上,我們與紅帽密切合作五年多。它的成功在很大程度上要歸功于我們有幸與之共事的優(yōu)秀紅帽工程師的努力。其他發(fā)行版和組織已經(jīng)并將從他們的努力中受益。

附帶說明一下,源代碼構(gòu)建是朝著可重現(xiàn)構(gòu)建邁出的一大步,我們也堅信這一點。.NET SDK 和 C# 編譯器具有重要的可重現(xiàn)構(gòu)建功能。

庫 API

除了已經(jīng)涵蓋的 API 之外,還添加了以下 API。

▌WebSocket 壓縮

壓縮對于通過網(wǎng)絡(luò)傳輸?shù)娜魏螖?shù)據(jù)都很重要。WebSockets 現(xiàn)在啟用壓縮。我們使用了WebSockets 的擴展permessage-deflate實現(xiàn),RFC 7692。它允許使用該DEFLATE算法壓縮 WebSockets 消息負(fù)載。此功能是 GitHub 上 Networking 的主要用戶請求之一。

與加密一起使用的壓縮可能會導(dǎo)致攻擊,例如CRIME和BREACH。這意味著不能在單個壓縮上下文中將秘密與用戶生成的數(shù)據(jù)一起發(fā)送,否則可以提取該秘密。為了讓用戶注意到這些影響并幫助他們權(quán)衡風(fēng)險,我們將其中一個關(guān)鍵 API 命名為DangerousDeflateOptions。我們還添加了關(guān)閉特定消息壓縮的功能,因此如果用戶想要發(fā)送秘密,他們可以在不壓縮的情況下安全地執(zhí)行此操作。

禁用壓縮時 WebSocket的內(nèi)存占用減少了約 27%。

從客戶端啟用壓縮很容易,如下例所示。但是,請記住,服務(wù)器可以協(xié)商設(shè)置,例如請求更小的窗口或完全拒絕壓縮。

var cws = new ClientWebSocket(); cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions() {ClientMaxWindowBits = 10,ServerMaxWindowBits = 10 };

還添加了對 ASP.NET Core 的 WebSocket 壓縮支持。

歸功于伊萬茲拉塔諾夫。

▌Socks 代理支持

SOCKS是一種代理服務(wù)器實現(xiàn),可以處理任何 TCP 或 UDP 流量,使其成為一個非常通用的系統(tǒng)。這是一個長期存在的社區(qū)請求,已添加到 .NET 6中。

此更改增加了對 Socks4、Socks4a 和 Socks5 的支持。例如,它可以通過 SSH 測試外部連接或連接到 Tor 網(wǎng)絡(luò)。

該類WebProxy現(xiàn)在接受socks方案,如以下示例所示。

var handler = new HttpClientHandler {Proxy = new WebProxy("socks5://127.0.0.1", 9050) }; var httpClient = new HttpClient(handler);

歸功于 Huo yaoyuan。

▌Microsoft.Extensions.Hosting — 配置主機選項 API

我們在 IHostBuilder 上添加了一個新的 ConfigureHostOptions API,以簡化應(yīng)用程序設(shè)置(例如,配置關(guān)閉超時):

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

在 .NET 5 中,配置主機選項有點復(fù)雜:

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

▌Microsoft.Extensions.DependencyInjection — CreateAsyncScope API

CreateAsyncScope 創(chuàng)建API是為了處理服務(wù)的處置 IAsyncDisposable。以前,您可能已經(jīng)注意到處置 IAsyncDisposable 服務(wù)提供者可能會引發(fā) InvalidOperationException 異常。

以下示例演示了新模式,CreateAsyncScope 用于啟用 using 語句的安全使用。

await using (var scope = provider.CreateAsyncScope()) {var foo = scope.ServiceProvider.GetRequiredService<Foo>(); }

以下示例演示了現(xiàn)有的問題案例:

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; }

以下模式是先前建議的避免異常的解決方法。不再需要它。

var scope = provider.CreateScope(); var foo = scope.ServiceProvider.GetRequiredService<Foo>(); await?((IAsyncDisposable)scope).DisposeAsync();

感謝 Martin Bj?rkstr?m 。

▌Microsoft.Extensions.Logging — 編譯時源生成器

.NET 6引入了LoggerMessageAttribute類型. 此屬性是Microsoft.Extensions.Logging 命名空間的一部分,使用時,它會源生成高性能日志記錄 API。源生成日志支持旨在為現(xiàn)代 .NET 應(yīng)用程序提供高度可用和高性能的日志解決方案。自動生成的源代碼依賴于 ILogger 接口和 LoggerMessage.Define功能。

LoggerMessageAttribute 源生成器在用于 partial 日志記錄方法時觸發(fā)。當(dāng)被觸發(fā)時,它要么能夠自動生成 partial 它正在裝飾的方法的實現(xiàn),要么生成編譯時診斷,并提供有關(guān)正確使用的提示。編譯時日志記錄解決方案在運行時通常比現(xiàn)有的日志記錄方法快得多。它通過最大限度地消除裝箱、臨時分配和副本來實現(xiàn)這一點。

與直接手動使用 LoggerMessage.Define API 相比,有以下好處:

  • 更短更簡單的語法:聲明性屬性使用而不是編碼樣板。

  • 引導(dǎo)式開發(fā)人員體驗:生成器發(fā)出警告以幫助開發(fā)人員做正確的事情。

  • 支持任意數(shù)量的日志記錄參數(shù)。LoggerMessage.Define 最多支持六個。

  • 支持動態(tài)日志級別。這是 LoggerMessage.Define 單獨不可能的。

要使用 LoggerMessageAttribute,消費類和方法需要是 partial。代碼生成器在編譯時觸發(fā)并生成 partial 方法的實現(xiàn)。

public static partial class Log {[LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]public static partial void CouldNotOpenSocket(ILogger logger, string hostName); }

在前面的示例中,日志記錄方法是 static,并且在屬性定義中指定了日志級別。在靜態(tài)上下文中使用屬性時,ILogger 需要實例作為參數(shù)。您也可以選擇在非靜態(tài)上下文中使用該屬性。有關(guān)更多示例和使用場景,請訪問編譯時日志記錄源生成器文檔。

▌System.Linq — 可枚舉的支持 Index 和 Range 參數(shù)

該 Enumerable.ElementAt 方法現(xiàn)在接受來自可枚舉末尾的索引,如以下示例所示。

Enumerable.Range(1, 10).ElementAt(^2); // returns 9

添加了一個 Enumerable.Take 接受 Range 參數(shù)的重載。它簡化了對可枚舉序列的切片:

  • source.Take(..3)代替source.Take(3)

  • source.Take(3..)代替source.Skip(3)

  • source.Take(2..7)代替source.Take(7).Skip(2)

  • source.Take(^3..)代替source.TakeLast(3)

  • source.Take(..^3)代替source.SkipLast(3)

  • source.Take(^7..^3)而不是.source.TakeLast(7).SkipLast(3)

感謝@dixin 。

▌System.Linq —TryGetNonEnumeratedCount

該 TryGetNonEnumeratedCount 方法嘗試在不強制枚舉的情況下獲取源可枚舉的計數(shù)。這種方法在枚舉之前預(yù)分配緩沖區(qū)很有用的場景中很有用,如下面的示例所示。

List<T> buffer = source.TryGetNonEnumeratedCount(out int count) ? new List<T>(capacity: count) : new List<T>(); foreach (T item in source) {buffer.Add(item); }

TryGetNonEnumeratedCount 檢查實現(xiàn) ICollection/ ICollection<T>或利用Linq 采用的一些內(nèi)部優(yōu)化的源。

▌System.Linq — DistinctBy/ UnionBy/ IntersectBy/ExceptBy

新變體已添加到允許使用鍵選擇器函數(shù)指定相等性的集合操作中,如下例所示。

Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) }; var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) }; first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }

▌System.Linq - MaxBy/MinBy

MaxBy 和 MinBy 方法允許使用鍵選擇器查找最大或最小元素,如下例所示。

var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) }; people.MaxBy(person => person.Age); // ("Ashley", 40)

▌System.Linq —Chunk

Chunk可用于將可枚舉的源分塊為固定大小的切片,如下例所示。

IEnumerable<int[]> chunks = Enumerable.Range(0, 10).Chunk(size: 3); // { {0,1,2}, {3,4,5}, {6,7,8}, {9} }

歸功于羅伯特安德森。

▌System.Linq—— //FirstOrDefault 采用默認(rèn)參數(shù)的重載LastOrDefaultSingleOrDefault

如果源可枚舉為空,則現(xiàn)有的 FirstOrDefault /LastOrDefault /SingleOrDefault 方法返回 default(T)。添加了新的重載,它們接受在這種情況下返回的默認(rèn)參數(shù),如以下示例所示。?

Enumerable.Empty<int>().SingleOrDefault(-1); // returns -1

感謝@ Foxtrek64 。

▌System.Linq —Zip 接受三個可枚舉的重載

Zip方法現(xiàn)在支持組合三個枚舉,如以下示例所示。

var xs = Enumerable.Range(1, 10);var ys = xs.Select(x => x.ToString());var zs = xs.Select(x => x % 2 == 0);foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs)){}

歸功于 Huo yaoyuan 。

▌優(yōu)先隊列

PriorityQueue<TElement, TPriority>(System.Collections.Generic) 是一個新集合,可以添加具有值和優(yōu)先級的新項目。在出隊時,PriorityQueue 返回具有最低優(yōu)先級值的元素。您可以認(rèn)為這個新集合類似于Queue<T>但每個入隊元素都有一個影響出隊行為的優(yōu)先級值。

以下示例演示了.PriorityQueue<string, int>

// creates a priority queue of strings with integer priorities var pq = new PriorityQueue<string, int>();// enqueue elements with associated priorities pq.Enqueue("A", 3); pq.Enqueue("B", 1); pq.Enqueue("C", 2); pq.Enqueue("D", 3);pq.Dequeue(); // returns "B" pq.Dequeue(); // returns "C" pq.Dequeue(); // either "A" or "D", stability is not guaranteed.

歸功于 Patryk Golebiowski。

精彩攻略歡迎繼續(xù)轉(zhuǎn)到下篇文章,繼續(xù)閱讀哦!

往期精彩回顧

▎.NET 6 攻略大全(一)

▎.NET 6 攻略大全(二)

?了解更多.NET?

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的.NET 6 攻略大全(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。