參考連接:
1.https://docs.microsoft.com/zh-cn/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay
2.https://www.cnblogs.com/dacc123/p/10644816.html
3.https://www.cnblogs.com/tiger-wang/p/14029853.html
介紹:
.NET Core 2.1 和 C# 7.2 帶來了 Span 的原生支持,原本需要使用不安全代碼操作的內存塊現在可以使用安全的方式來完成。此前在性能和穩定性上需要有所取舍,而現在可以兼得了。
Span< T > : 結構體,值類型 。相當於C++ 中的指針,它是一段連續內存的引用,也就是一段連續內存的首地址。使用的是堆棧內存。有了Span< T >,我們就可以不在unsafe的代碼塊中寫指針了。
使用:
應用1:允許截取數組中的一段,直接通過指針操作。在使用中,Span確保了內存和數據安全,而且幾乎沒有開銷。
var arr = new byte[10]; Span<byte> bytes = arr; bytes [0] = 42;
應用2:高效的字符串操作。string.Substring() 函數,實際上是在堆中額外創建了一個新的 string 對象,把字符 copy 過去,再返回這個對象的引用。而相對應的 Span< T > 的Slice() 函數則是直接在內存中返回子串的首地址引用,此過過程幾乎不分配內存,並且十分高效。因此可以用來做高效的字符串截取,也可以配合StringBuilder進行高效的字符串拼接。注:ReadOnlySpan為只讀的Span。
ReadOnlySpan<char> t = "abcde".AsSpan(2,2); ReadOnlySpan<char> t2 = tts.Slice(1, 3); int position = t.IndexOf(t2); string s = t.ToString(); StringBuilder sb = new StringBuilder(); sb.Append(t);
限制:
Span使用的是堆棧內存。所有指向堆棧的指針都不能存儲在托管堆上。因為方法結束時,堆棧會被釋放,指針會變成無效值,如果再使用,就是內存溢出。
因此Span實例也不能駐留在托管堆上,而只能駐留在堆棧上。這又引出一些限制。
1.Span不能作為非堆棧類型的字段
2.Span不能有接口實現
3.Span不能是異步方法的參數或局部變量
4.Span不能是泛型的代入參數
以上限制可以使用Memory<T>解決,這與處理 Span 基本相同,不同之處在於 Memory<T> 是不類似引用的結構,可以存在於堆上。然后,若要執行同步處理,可以從其屬性中獲取 Span<T>。