iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0

Span / Memory 互轉技巧

  • 字串與 char-span:
    • 取得:ReadOnlySpan<char> r = someString.AsSpan();
    • 建立字串:string newStr = new string(span); 或使用 string.Create(length, state, spanAction) 以避免額外中間分配的多次拷貝。
  • 位元組視圖:MemoryMarshal.AsBytes<T>(span)Span<T> 轉為 Span<byte>(注意對齊與相依型別安全性)。
  • Encoding 支援 span overloads(在現代 .NET):Encoding.UTF8.GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)Encoding.UTF8.GetString(ReadOnlySpan<byte> bytes)

像是以下例子,想要高效率 UTF-8 編碼到預先分配的 buffer

using System;
using System.Text;

Span<byte> outBuf = stackalloc byte[128];
ReadOnlySpan<char> text = "Hello 世界".AsSpan();
int written = Encoding.UTF8.GetBytes(text, outBuf);
// 現在 outBuf.Slice(0, written) 包含 UTF-8 bytes

要注意

  • 嘗試把 Span<T> 放到類的欄位或用作 async/await 中的局部變數會導致編譯錯誤或不可預期的行為,編譯器會阻止這些用法。
  • 使用 stackalloc 或來自非托管記憶體的 Span<T> 時要注意生命週期,千萬不要將資料引用回傳給呼叫端。若要回傳,可考慮 Memory<T> 搭配 MemoryPool。
  • Memory<T>.Pin()MemoryMarshal.GetReference() 可以在需要 pin 時使用,但務必在 fixed 或受控區塊內使用以避免 GC moving 導致的問題。

建議

  1. 讀取/解析大量或頻繁的小資料請使用 Span<T> 來避免分配。若操作必須跨越非同步邊界,使用 Memory<T> + IMemoryOwner<T>(MemoryPool)。
  2. 不要用 Substring 在熱路徑建立大量臨時字串,改用 ReadOnlySpan<char>
  3. 對 UTF-8 進行編碼/解碼時,優先使用 Encoding 的 span-overloads 以避免中間陣列。
  4. 當需要把緩衝區傳給本機函式時,要 pin 記憶體並小心處理 lifetime,需要注意 prefer fixed + MemoryMarshal.GetReference 或 GCHandle。

像是我們可以用 Span 實作簡單的 CSV 欄位拆分,能達到同步、無分配

using System;

void PrintCsvFields(ReadOnlySpan<char> line)
{
        while (!line.IsEmpty)
        {
                int idx = line.IndexOf(',');
                if (idx == -1)
                {
                        Console.WriteLine(line.ToString());
                        break;
                }
                var field = line.Slice(0, idx);
                Console.WriteLine(field.ToString());
                line = line.Slice(idx + 1);
        }
}

PrintCsvFields("a,b,c,d".AsSpan());

在微軟設計中,字串提供了方便且不可變的字元序列表現,Span<T> 提供低延遲、零分配的同步操作視圖;Memory<T> 則是在需要可傳遞、長期保留或跨 async 邊界時的安全選擇。


上一篇
BCL 字串、Span<T>、Memory<T>
下一篇
Task/ValueTask 與非同步排程器原始碼導讀
系列文
新 .NET & Azure & IoT & AI 開源技術實戰手冊 (含深入官方程式碼講解) 22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言