はじめに
今回はunsafe
を用いずにReadOnlySpan<Span>
からSpan<char>
に変換する方法について紹介をしたいと思います。
ReadOnlySpan<char> str = "hello, world"; var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(str), str.Length); // unsafe使わずともこれで簡単にいじれてしまうやん... span.Reverse(); // dlrow ,olleh Console.WriteLine(str.ToString()); Console.WriteLine(span.ToString());
概要
Span
に変更するためにはMemoryMarshal.CreateSpan
とMemoryMarshal.GetReference
を組み合わせます。
MemoryMarshal.CreateSpan
public static Span<T> CreateSpan<T> (scoped ref T reference, int length);
定期的なマネージド オブジェクトの一部に対する新しいスパンを作成します。
reference
に先頭のアドレスを渡し、あとはlength
で要素数を渡してあげればSpan
を生成できます。
MemoryMarshal.GetReference
public static ref T GetReference<T> (ReadOnlySpan<T> span); public static ref T GetReference<T> (Span<T> span);
インデックス 0 にある(読み取り専用)スパンの要素の参照を返します。
先頭のアドレスを取得します。ReadOnlySpan
の方のオーバーロードを今回は利用していきます。
やり方
ReadOnlySpan<char> str = "hello, world"; var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(str), str.Length); // unsafe使わずともこれで簡単にいじれてしまうやん... span.Reverse(); span[0] = 'A'; // Alrow ,olleh Console.WriteLine(str.ToString()); Console.WriteLine(span.ToString());
Span
に対して操作をすれば、同じメモリ領域を指しているので中身を好き勝手いじれるというわけですね。
もはやReadOnly
は中身を書き換えないでねという意思表示になっているといってもいいかもしれません。