---
# System prepended metadata

title: Span<T>
tags: ['2022', C#]

---

###### tags: `C#`,`2022`

# Span<T>

C#7.2新增的功能。 
    
```csharp=
readonly ref struct Span<T> {
    readonly ref T _pointer;
    readonly int _length;
    
    public ref T this[int index] => ...
}
``` 

_pointer是紀錄記憶體指定的位置
    
_length 是從這個位置連續存取的長度
    
Span<T> 是struct結構，ref T支援直接返回引用，這樣就無需通過計算來確定指標開頭、起始偏移，從而真正擁有和訪問陣列一樣高的效率。


這裡有分為Slow Span 和 Fast Span
這裡先記得只有兩個引數(ref本身和長度欄位)稱為Fast Span，原生有支援，操作Get、Set的效能和陣列差不多

## Stack-Only

Span<T>會把資料存放在stack上，靜態分配，有限制大小，會自動釋放記憶體，因此有以下設限
    
* 不能用在類別的屬性   
* 不能在介面上實作
* 不能用在非同步方法的參數
* 不能為泛行參數
* 不能用在Lamnda、iterator

### 非同步應用 Memory<T>

如果想要在非同步應用，可以使用Memory<T>或是ReadOnlyMemory<T>，可存放連續記憶體，並且無限制大小
    
## AsSpan()

可以取代Substring()，效能更好更快，個人覺得還滿好用的。
這裡AsSpan()傳出的型別會是ReadOnlySpan<char>
    
```csharp=
var text = "ABCgoogleIEYahoo";

//從第8個字開始取6個位元
var name = text.AsSpan(3, 6);

var builder = new StringBuilder("Hi ");
builder.Append(name);
builder.AppendLine("!");
    
Console.WriteLine(builder.ToString());
```

另一種用法，搭配Slice() 可以達成用逗號區擷取前後數值

```csharp=
   var input = "123,456";
   var inputSpan = input.AsSpan();
   var commaPos = input.IndexOf(',');
    
    // no-Allocating, no-Coping
   var first = int.Parse(inputSpan.Slice(0, commaPos));
   var second = int.Parse(inputSpan.Slice(commaPos + 1));
```

## 總結
    
對於字串的處理，Span可以提昇效能，減少浪費

## Reference
[Unserstand Span](https://docs.microsoft.com/zh-tw/events/connect-2017/t125)
 

    

{%hackmd BJrTq20hE %}