今回はSpan<T>およびReadOnlySpan<T>のより暗黙的な変換という機能について解説します。これも型指定を省略できるようになる、というC# 14の改良点のひとつです。
Span<T>とは
Span<T>は、配列の一部または全体をコピーせずにやり取りするための型です。通常の配列は、メソッドなどに引き渡すときにコピーされます。配列をコピーして渡すと、余計なメモリを使ったりパフォーマンス上の問題が出たりすることがあります。そこで引数の型をSpan<int>のようにしておくと、コピーではなく配列そのものを参照する形で受け渡しができます。
プロジェクトを作成する
Visual Studio 2026で新しいプロジェクトを作成します。テンプレートは「Windows フォーム アプリ」(C#)、ターゲットフレームワークは .NET 10.0 を選択します。
図1: Visual Studio 2026 の起動画面から「新しいプロジェクトの作成」を選ぶ
図2: フレームワークに .NET 10.0(長期的なサポート)を選択する
配列とSpan<T>
Form1のコンストラクター内でint型の配列を用意します。
int[] array = { 1, 2, 3, 4, 5 };
続けて、配列を受け取るCallIntメソッドを定義します。最初はint[]で受け取る形にしますが、これをSpan<int>に書き換えます。入力中にSpan<T>と打つと、インテリセンスで「型セーフかつメモリセーフに、連続した領域を表現する」という説明が表示されます。
図3: Span<T>のインテリセンス説明。連続した領域を型セーフ・メモリセーフに表現する型であることが分かる
private void CallInt(Span<int> values)
{
}
呼び出し側はCallInt(array);のように、これまでどおり配列をそのまま渡すだけでよく、コード変更は不要です。int[]の配列は暗黙的にSpan<int>へ変換されるため、このままコンパイルが通ります。
図4: CallInt(array)の呼び出し。引数の型はSpan<int>だが、配列がそのまま暗黙的に変換されて渡っている
AsSpanで配列の一部だけを渡す
array.AsSpan(1, 3)のように書くと、配列全体ではなく一部分だけを切り出してSpanとして渡すことができます。第一引数が開始位置(0始まりのインデックス)、第二引数が長さです。array.AsSpan(1, 3)は、インデックス1から3個分、つまり値2, 3, 4の部分を表すSpanになります。
図5: array.AsSpan(1, 3)のインテリセンス説明。「対象配列の、指定した位置から指定した長さ分の範囲を表すSpanを新しく作成する」という内容が確認できる
CallInt(array.AsSpan(1, 3));
汎用的な型パラメーターの場合
ここまではintに固定した場合でした。次に、型パラメーターTを使って汎用的にしたCallメソッドを考えます。
private T Call<T>(Span<T> values)
{
return values[0];
}
この場合、C# 13までは配列を暗黙的にSpan<T>に型変換するときに、型パラメーターの型指定が必要でした。つまりCall(array);のように型指定を省略すると型を推論できずエラーになり、Call<int>(array);のように山括弧でintを明示的に指定する必要がありました。
図6: C# 13までは、Call<int>(array);のように型引数intを明示的に指定する必要があった
実際に型指定を省略してCall(array);と書くと、C# 13の時点ではエラーになります。
図7: C# 13のままCall(array);と型指定を省略すると、エラーが発生する(左下に赤字で「1」件のエラー表示)
C# 14では型指定が不要になる
プロジェクトのターゲットフレームワークを.NET 10.0(C# 14)に変更すると、同じCall(array);というコードがそのままエラーなく通るようになります。配列をSpan<T>に暗黙的に変換する際に必要だった型パラメーターの型指定が、不要になったということです。
図8: .NET 10(C# 14)にすると、型指定なしのCall(array);でもエラーが出ずコンパイルが通る
ReadOnlySpan<T>でも同様
ここまではSpan<T>の場合でしたが、ReadOnlySpan<T>についても同じ改良がされています。Call<T>メソッドの引数をSpan<T>からReadOnlySpan<T>に変えても、C# 14であれば型指定なしのCall(array);がそのまま通ります。
図9: 引数をReadOnlySpan<T>に変えても、型指定なしのCall(array);は同じようにエラーなくコンパイルできる
まとめ
配列をSpan<T>やReadOnlySpan<T>に暗黙的に型変換する際、型パラメーターを持つメソッドではC# 13まで型指定(例: Call<int>(array))が必要でしたが、C# 14ではその型指定を省略してCall(array)のように書けるようになりました。これもC# 14における「型指定の省略」を実現する改良のひとつです。
Udemyでの動画版はこちらからご覧いただけます
00_はじめに
01_VisualStudio2026をインストールしてください
A01_fieldキーワード
B01_extensionブロックとは
B02_拡張メソッドとは
B03_extensionブロック
B04_型パラメータありの拡張メソッド
B05_型パラメータありのextensionブロックの書き方
B06_拡張プロパティ
B07_拡張静的プロパティ&メソッド
B08_拡張演算子
C01_partialコンストラクター
C02_幽霊コードを定義パーツで契約による実装をするという考え方
C03_partialイベント
D01_Null条件付き代入
E01_複合代入演算子のオーバーロード
F01_明示的な型を指定せずにラムダパラメータでパラメータ修飾子を使用する
G01_nameofはバインドされていないジェネリック型をサポートします
H01_SpanTおよびReadOnlySpanTのより暗黙的な変換
Udemyでの動画版はこちらからご覧いただけます