C# 7.2以降で追加されたSpan<T>
構造体や配列などに追加された演算子についての備忘録です。
Span<T>構造体
Span<T>
構造体とは、配列などのデータが並んでいるものから一部を取り出して、値を読み書きするものです。
Span<T>
構造体は、ref 構造体という参照型の構造体になっていて、文字列などの連続したメモリ領域を直接参照できるので、バイナリデータなどに対してもC言語のポインターのような感覚で安全に扱うことができます。おまけに高速です。
また、読み取り専用のReadOnlySpan<T>
構造体も提供されています。
配列を参照する
// int型の配列 var array = new int[]{ 2022, 1, 23, 4, 0 }; // 2番目から2要素分の参照 var spanData = new Span<int>(array, 1, 2); foreach (var val in spanData) { Console.Write(val); // 123が出力される } spanData[0] = 5; // spanDataの1番目を書き換える foreach (var val in array) { Console.Write(val); // 202252340が出力される }
文字列を参照する
以下は、ReadOnlySpan<T>
構造体を返す拡張メソッドのAsSpan
を使用したサンプルです。
なお、Slice
メソッドは位置と長さを指定してデータを切り出すメソッドです。
// 3文字目から3文字を切り出し var spanData2 = "XXABCXXX".AsSpan().Slice(2, 3); foreach (var val in spanData2) { Console.Write(val); // "ABC" が出力される }
C#のstring型は変更できないオブジェクトなので、AsSpan
メソッドは読み取り専用のReadOnlySpan
を返却します。
よって、上記のspanData2は、ReadOnlySpan
なので書き換えできません。
なお、配列に対してAsSpan
メソッドを使う場合は、Span
を返します。
インデックスと範囲の演算子「^」「..」
C# 8.0で追加された演算子^
と..
を使うと、範囲を指定する構文がシンプルに記述できるようになりました。
Span<T>
やReadOnlySpan<T>
に範囲を指定する際にも使用できます。
例) ^N: 末尾からN番目
N..^M: N+1からM番目。※先頭の位置は0から数える。
var array = new int[]{ 2022, 1, 23, 4, 0 }; // 末尾から3番目 Console.WriteLine(array [^3]); // 23が出力される // 2~4番目 var span = array.AsSpan()[1..4]; foreach (var val in span) { Console.Write(val); // 1234が出力される }