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
変数はawait
メソッド内のasync
式と同じブロック内で使用できません。 ただし、同期メソッドでは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 以降では、型パラメーターのref struct
句でallows ref struct
を指定する場合、where
を型引数として使用できます。
通常、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
で ref struct
フィールドを宣言できます。
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
値を指定できます。 Unsafe.IsNullRef<T>(T) フィールドが ref
であるかどうかを判断するには、null
メソッドを使用します。
readonly
修飾子は、次の方法で ref
フィールドに適用できます。
readonly ref
: コンストラクターまたは= ref
内でのみ、このようなフィールドをinit
演算子を使用して 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
が破棄可能なパターンに適合するようにします。 つまり、これには、アクセス可能かつパラメーターなしの、Dispose
の戻り値型を持つ、インスタンス void
メソッドが含まれます。 using ステートメントまたは宣言は、破棄可能な ref struct
のインスタンスと共に使用できます。
C# 13 以降では、IDisposable 型に ref struct
を実装することもできます。 ただし、オーバーロードの解決では、インターフェイス メソッドよりも破棄可能なパターンが優先されます。 コンパイラは、適切なIDisposable.Dispose
メソッドが見つからない場合にのみ、Dispose
メソッドに解決されます。
インターフェイスを実装する ref struct
型の制限事項
これらの制限事項があるため、インターフェイスを実装する ref struct
型が必要な ref 安全性規則に確実に従うことができます。
ref struct
を、それが実装するインターフェイスのインスタンスに変換することはできません。 この制限事項には、パラメーターがインターフェイス型の場合にref struct
型を引数として使用する場合の暗黙的な変換が含まれます。 変換によってボックス化変換が行われるので、参照の安全性に違反します。ref struct
は、明示的なインターフェイス宣言としてメソッドを宣言できます。 ただし、これらのメソッドは、型パラメーターallows ref struct
が存在するジェネリック メソッドからのみアクセス可能です。- インターフェイス を実装する
ref struct
は、すべてのインスタンス インターフェイス メンバー 実装する必要があります。 インターフェイスに既定の実装が含まれている場合でも、ref struct
はインスタンス メンバーを実装する必要があります。
コンパイラはこれらの制限事項を適用します。 インターフェイスを実装する ref struct
型を作成すると、新しい更新プログラムごとに新しい既定のインターフェイス メンバーが含まれる可能性があります。 新しいインスタンス メソッドの実装を提供するまで、アプリケーションはコンパイルされません。 既定の実装を使用して、static
インターフェイス メソッドの特定の実装を指定することはできません。
重要
インターフェイスを実装する ref struct
には、後でソース破壊的およびバイナリ破壊的変更が行われる可能性があります。 ref struct
が別のアセンブリで定義されたインターフェイスを実装し、そのアセンブリがそのインターフェイスに既定のメンバーを追加する更新プログラムを提供する場合、中断が発生します。
ソース中断は、ref struct
を再コンパイルするときに発生します。既定の実装がある場合でも、新しいメンバーを実装する必要があります。
バイナリ中断は、ref struct
型を再コンパイルせずに外部アセンブリをアップグレードし、"かつ" 更新されたコードが新しいメソッドの既定の実装を呼び出す場合に発生します。 既定のメンバーにアクセスすると、ランタイムは例外をスローします。
C# 言語仕様
詳細については、「C# 言語仕様」の次のセクションを参照してください。
ref
フィールドの詳細については、「低レベル構造体の機能強化」の提案メモを参照してください。
関連項目
.NET