ref
構造体型 (C# リファレンス)
ref
修飾子は、構造体型の宣言内で使用できます。 ref struct
型のインスタンスはスタック上に割り当てられます。マネージド ヒープにエスケープすることはできません。 これを確実にするために、コンパイラでは次のように ref struct
型の使用が制限されます。
ref struct
を配列の要素型にすることはできません。ref struct
をクラスまたは非ref struct
のフィールドの宣言型にすることはできません。ref struct
を System.ValueType または System.Object にボックス化することはできません。ref struct
変数をラムダ式またはローカル関数の中にキャプチャすることはできません。- C# 13 より前のバージョンでは、
ref struct
変数をasync
メソッドで使用できません。 C# 13 以降では、ref struct
変数はasync
メソッド内のawait
式と同じブロック内で使用できません。 ただし、同期メソッドではref struct
変数を使用できます (Task または Task<TResult> を返すメソッドなど)。 - C# 13 より前では、
ref struct
変数は反復子の中で使用できません。 C# 13 以降では、ref struct
型とref
ローカルは、yield return
ステートメントを含むコード セグメントの中にない場合は、反復子の中で使用できます。 - C# 13 より前では、
ref struct
はインターフェイスを実装できません。 C# 13 以降、ref
構造体はインターフェイスを実装できますが、ref 安全性規則に従う必要があります。 たとえば、ref struct
型はボックス化変換が必要なため、インターフェイス型に変換できません。 - C# 13 より前では、
ref struct
を型引数にすることはできません。 C# 13 以降では、型パラメーターのwhere
句でallows ref struct
を指定する場合、ref struct
を型引数として使用できます。
通常、ref struct
型のデータ メンバーも含む型が必要な場合は、ref struct
型を定義します。
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
ref struct
を readonly
として宣言するには、型宣言内で readonly
修飾子と ref
修飾子を組み合わせます (readonly
修飾子は ref
修飾子よりも前にある必要があります)。
public readonly ref struct ConversionRequest
{
public ConversionRequest(double rate, ReadOnlySpan<double> values)
{
Rate = rate;
Values = values;
}
public double Rate { get; }
public ReadOnlySpan<double> Values { get; }
}
.NET では、ref struct
の例として System.Span<T> と System.ReadOnlySpan<T> があります。
ref
フィールド
C# 11 以降では、次の例に示すように、ref struct
で ref
フィールドを宣言できます。
public ref struct RefFieldExample
{
private ref int number;
public int GetNumber()
{
if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
{
throw new InvalidOperationException("The number ref field is not initialized.");
}
return number;
}
}
ref
フィールドには null
値を指定できます。 ref
フィールドが null
であるかどうかを判断するには、Unsafe.IsNullRef<T>(T) メソッドを使用します。
readonly
修飾子は、次の方法で ref
フィールドに適用できます。
readonly ref
: コンストラクターまたはinit
アクセサー内でのみ、このようなフィールドを= ref
演算子を使用して ref 再割り当てすることができます。 フィールド アクセス修飾子によって許可される任意の時点で、=
演算子を使用して値を割り当てることができます。ref readonly
: どの時点でも、このようなフィールドに=
演算子を使用して値を割り当てることはできません。 ただし、= ref
演算子を使用してフィールドを ref 再割り当てすることはできます。readonly ref readonly
: このようなフィールドは、コンストラクターまたはinit
アクセサーでのみ ref 再割り当てできます。 どの時点でも、このフィールドに値を割り当てることはできません。
コンパイラにより、ref
フィールドに格納されている参照が、そのリファレントより長く存在しないことが保証されます。
ref
フィールド機能を使用すると、System.Span<T> のような型を安全に実装できます。
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
Span<T>
型は、メモリ内の連続する要素にアクセスする参照を格納します。 参照を使用すると、Span<T>
インスタンスは参照先のストレージのコピーを回避できます。
破棄可能なパターン
破棄可能な ref struct
を定義できます。 そのためには、ref struct
が破棄可能なパターンに適合するようにします。 つまり、これには、アクセス可能かつパラメーターなしの、void
の戻り値型を持つ、インスタンス Dispose
メソッドが含まれます。 using ステートメントまたは宣言は、破棄可能な ref struct
のインスタンスと共に使用できます。
C# 13 以降では、ref struct
型に IDisposable を実装することもできます。 ただし、オーバーロードの解決では、インターフェイス メソッドよりも破棄可能なパターンが優先されます。 コンパイラは、適切な Dispose
メソッドが見つからない場合にのみ、IDisposable.Dispose
メソッドを解決します。
インターフェイスを実装する ref struct
型の制限事項
これらの制限事項があるため、インターフェイスを実装する ref struct
型が必要な ref 安全性規則に確実に従うことができます。
ref struct
を、それが実装するインターフェイスのインスタンスに変換することはできません。 この制限事項には、パラメーターがインターフェイス型の場合にref struct
型を引数として使用する場合の暗黙的な変換が含まれます。 変換によってボックス化変換が行われるので、参照の安全性に違反します。- インターフェイスを実装する
ref struct
は、すべてのインターフェイス メンバーを実装する "必要があります"。ref struct
は、インターフェイスに既定の実装が含まれるメンバーを実装する必要があります。
コンパイラはこれらの制限事項を適用します。 インターフェイスを実装する ref struct
型を作成すると、新しい更新プログラムごとに新しい既定のインターフェイス メンバーが含まれる可能性があります。 これらの新しいメソッドの実装を用意するまで、アプリケーションはコンパイルできません。
重要
インターフェイスを実装する ref struct
には、後でソース破壊的およびバイナリ破壊的変更が行われる可能性があります。 ref struct
が別のアセンブリで定義されたインターフェイスを実装し、そのアセンブリがそのインターフェイスに既定のメンバーを追加する更新プログラムを提供する場合、中断が発生します。
ソース中断は、ref struct
を再コンパイルするときに発生します。既定の実装がある場合でも、新しいメンバーを実装する必要があります。
バイナリ中断は、ref struct
型を再コンパイルせずに外部アセンブリをアップグレードし、"かつ" 更新されたコードが新しいメソッドの既定の実装を呼び出す場合に発生します。 既定のメンバーにアクセスすると、ランタイムは例外をスローします。
C# 言語仕様
詳細については、「C# 言語仕様」の次のセクションを参照してください。
ref
フィールドの詳細については、「低レベル構造体の機能強化」の提案メモを参照してください。
関連項目
.NET