LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C# 中的 Span:高效編碼的最佳朋友

admin
2024年9月13日 10:5 本文熱度 946

以提高 C# 代碼中 Collections 和 Arrays 的性能和內(nèi)存使用率(您還記得 String 是一個(gè)字符數(shù)組,加載方式略有不同,但無(wú)論如何)。我終于設(shè)法找到了一些時(shí)間來(lái)更深入地研究 System.Span。

我整理了本指南來(lái)分享我所學(xué)到的知識(shí)。它充滿(mǎn)了實(shí)用的技巧和示例,可幫助您在自己的項(xiàng)目中利用 Span。如果您想優(yōu)化 C# 代碼,本指南是一個(gè)很好的起點(diǎn)!

那么,您想讓 C# 代碼運(yùn)行得更快并更有效地使用內(nèi)存嗎?認(rèn)識(shí) Spans:一款方便的工具,可簡(jiǎn)化內(nèi)存塊的處理并幫助您的應(yīng)用程序獲得更好的性能。讓我們深入了解 Span 的工作原理,探索實(shí)際示例,了解它們的區(qū)別,并了解如何將它們用于 JSON 解析,以及將集合與 Span 相互轉(zhuǎn)換。

什么是 Span?

在 C# 中,是表示內(nèi)存的連續(xù)區(qū)域的結(jié)構(gòu)。它們?cè)试S您處理數(shù)據(jù)切片,而不會(huì)產(chǎn)生額外內(nèi)存分配的開(kāi)銷(xiāo)。Span<T>ReadOnlySpan<T>

  • Span<T>:允許對(duì)內(nèi)存進(jìn)行讀取和寫(xiě)入操作。

  • ReadOnlySpan<T>:用于只讀操作,確保數(shù)據(jù)無(wú)法修改。

Span 對(duì)于性能關(guān)鍵型方案特別有用,因?yàn)樗鼈冎С种苯釉L問(wèn)數(shù)據(jù)和高效使用內(nèi)存。

為什么應(yīng)該關(guān)心 Span?

  1. 更快的性能:Span 有助于減少內(nèi)存分配和垃圾回收壓力。它們?cè)试S您直接有效地處理數(shù)據(jù)。

  2. 更安全的代碼:Span 可防止緩沖區(qū)溢出等常見(jiàn)錯(cuò)誤,并提供邊界檢查。

  3. 多功能性:它們適用于其他內(nèi)存區(qū)域的數(shù)組、字符串和切片,使其適用于各種數(shù)據(jù)處理場(chǎng)景。

Span 是如何實(shí)現(xiàn)的

在后臺(tái),Span 被設(shè)計(jì)為輕量級(jí)和快速:

  • 堆棧分配:跨度通常在堆棧上分配,這樣速度更快并避免堆分配。

  • 內(nèi)存安全:它們確保對(duì)內(nèi)存的安全訪問(wèn),并內(nèi)置邊界檢查以防止越界錯(cuò)誤。

  • 無(wú)堆開(kāi)銷(xiāo):與數(shù)組不同,Span 不會(huì)創(chuàng)建額外的堆分配,從而減少內(nèi)存開(kāi)銷(xiāo)并提高性能。

和 之間的差異Span<T>ReadOnlySpan<T>

雖然兩者 和 處理連續(xù)內(nèi)存,但它們的用法和功能不同:Span<T>ReadOnlySpan<T>

Span<T>:

  • 可變:您可以修改 .Span<T>

  • 示例:更改數(shù)組或緩沖區(qū)中的元素。

int[] numbers = { 1, 2, 3, 4, 5 };
Span<int> span = new Span<int>(numbers);
span[0] = 10; // Modifies the original array
Console.WriteLine(numbers[0]); // Outputs 10

ReadOnlySpan<T>:

  • Immutable:您無(wú)法修改 .ReadOnlySpan<T>

  • 示例:從字符串或數(shù)組中讀取值而不更改它們。

string text = "Hello, World!";
ReadOnlySpan<char> readOnlySpan = text.AsSpan();
// readOnlySpan[0] = 'h'; // This line would cause a compilation error
Console.WriteLine(readOnlySpan.ToString()); // Outputs "Hello, World!"

集合到 Span 的轉(zhuǎn)換

Span 旨在與數(shù)組等集合無(wú)縫協(xié)作,從而可以輕松地在集合和 Span 之間進(jìn)行轉(zhuǎn)換。

從array到 Span:

int[] numbers = { 1, 2, 3, 4, 5 };
Span<int> spanFromArray = new Span<int>(numbers);

從 span 到 array:

Span<int> span = stackalloc int[] { 1, 2, 3, 4, 5 };
int[] arrayFromSpan = span.ToArray();

從 String 到 ReadOnlySpan:

string text = "Hello, World!";
ReadOnlySpan<char> spanFromString = text.AsSpan();

從 ReadOnlySpan 到 String:

ReadOnlySpan<char> span = "Hello, World!".AsSpan();
string strFromSpan = span.ToString(); // Note: Converts to a new string

集合轉(zhuǎn)換的實(shí)際示例

示例:使用數(shù)組和 Span

int[] array = { 1, 2, 3, 4, 5 };
Span<int> span = array;
span[0] = 10; // Modifies the original array
Console.WriteLine(string.Join(", ", array)); // Outputs: 10, 2, 3, 4, 5

示例:將 Span 轉(zhuǎn)換為數(shù)組

Span<int> span = stackalloc int[] { 10, 20, 30 };
int[] array = span.ToArray();
Console.WriteLine(string.Join(", ", array)); // Outputs: 10, 20, 30

示例:使用 ReadOnlySpan 提取子字符串

string text = "Hello, World!";
ReadOnlySpan<char> span = text.AsSpan();
ReadOnlySpan<char> helloSpan = span.Slice(0, 5);
Console.WriteLine(helloSpan.ToString()); // Outputs: Hello

實(shí)際示例:使用 Span 編寫(xiě)自己的 JSON 解析器

Span 對(duì)于有效處理字符串?dāng)?shù)據(jù)特別有用。所以現(xiàn)在讓我們嘗試編寫(xiě)我們自己的 JSON 解析器,它可以在不創(chuàng)建不必要的中間字符串的情況下工作。

簡(jiǎn)單的 JSON 解析器

public void ParseJson(ReadOnlySpan<char> jsonData)
{
   // Find the start of the value for a specific key
   ReadOnlySpan<char> key = "name";
   int keyStart = jsonData.IndexOf(key);
   
   if (keyStart == -1)
   {
       Console.WriteLine("Key not found");
       return;
   }
   
   // Move past the key and find the colon
   int valueStart = jsonData.Slice(keyStart + key.Length).IndexOf(':') + keyStart + key.Length + 1;
   int valueEnd = jsonData.Slice(valueStart).IndexOf(',');
   
   if (valueEnd == -1) // If no comma, this is the last value
   {
       valueEnd = jsonData.Slice(valueStart).IndexOf('}');
   }
   
   // Extract and print the value
   ReadOnlySpan<char> value = jsonData.Slice(valueStart, valueEnd);
   Console.WriteLine(value.ToString().Trim('"')); // Remove quotes
}

解析器非常適合原子數(shù)據(jù)類(lèi)型,但不支持 Array 或內(nèi)部 Object 等復(fù)雜類(lèi)型。

因此,讓我們添加一個(gè)基于 Span  Array 解析器:

public void ProcessJsonArray(ReadOnlySpan<char> jsonArray)
{
   int currentIndex = 0;
   
   while (currentIndex < jsonArray.Length)
   {
       int start = jsonArray.Slice(currentIndex).IndexOf('{');
       if (start == -1) break; // No more objects

       int end = jsonArray.Slice(currentIndex).IndexOf('}');
       if (end == -1) break; // Incomplete object
       
       ReadOnlySpan<char> jsonObject = jsonArray.Slice(currentIndex + start, end - start + 1);
       ProcessJsonObject(jsonObject);
       
       currentIndex += end + 1; // Move past the current object
   }
}

并添加嵌套對(duì)象支持:

private void ProcessJsonObject(ReadOnlySpan<char> jsonObject)
{
   // Simple key-value extraction, assuming keys and values are properly formatted
   int colonIndex = jsonObject.IndexOf(':');
   ReadOnlySpan<char> key = jsonObject.Slice(1, colonIndex - 2); // Skipping surrounding quotes
   ReadOnlySpan<char> value = jsonObject.Slice(colonIndex + 1).Trim(); // Extract value and trim
   
   Console.WriteLine($"Key: {key.ToString()}, Value: {value.ToString()}");
}

將所有內(nèi)容放在一起:解析 JSON 數(shù)據(jù)

以下是結(jié)合使用上述所有函數(shù)來(lái)解析完整 JSON 字符串的方法:

public void ParseJson(ReadOnlySpan<char> jsonData)
{
   int start = 0;
   while (start < jsonData.Length)
   {
       int objectStart = jsonData.Slice(start).IndexOf('{');
       if (objectStart == -1) break;

       int objectEnd = jsonData.Slice(start).IndexOf('}');
       if (objectEnd == -1) break;

       ReadOnlySpan<char> jsonObject = jsonData.Slice(start + objectStart, objectEnd - objectStart + 1);
       ProcessJsonObject(jsonObject);

       start += objectEnd + 1;
   }
}

干的好!現(xiàn)在我們有了自己的內(nèi)存有效型 JSON 解析器實(shí)現(xiàn),終于可以忘記這些 Newtonsoft.Json nuget 包更新問(wèn)題了......可能最近 3 到 4 年都沒(méi)有面對(duì)它,因?yàn)?Microsoft 編寫(xiě)了自己的實(shí)現(xiàn),但如果你面對(duì) - 現(xiàn)在你知道該怎么做了!

需要注意的事項(xiàng)

  • 范圍:Span 是堆棧分配的,應(yīng)在創(chuàng)建它們的方法中使用。

  • 固定:在處理非托管內(nèi)存時(shí),請(qǐng)謹(jǐn)慎使用固定,因?yàn)樗赡軙?huì)影響垃圾回收。

  • 兼容性:確保您的開(kāi)發(fā)環(huán)境支持 Span,尤其是對(duì)于較舊的框架。

Span 是 C# 中的一項(xiàng)強(qiáng)大功能,可以幫助您高效安全地管理內(nèi)存。通過(guò)了解 和 之間的差異,以及如何在集合和 span 之間進(jìn)行轉(zhuǎn)換,您可以編寫(xiě)更高效、更簡(jiǎn)潔的代碼。將 Span 用于任務(wù)Span<T>ReadOnlySpan<T>


該文章在 2024/9/13 10:05:31 編輯過(guò)
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
伊人久久大香线蕉综合网蜜芽 | 午夜欧美日韩在线视频二区 | 亚洲欧美精品综合欧美一区 | 久久综合精品网站动漫 | 宅女午夜福利免费视频 | 天天看高清国产在线 |