ref 構造体型 (C# リファレンス)

ref 修飾子は、構造体型の宣言内で使用できます。 ref struct 型のインスタンスはスタック上に割り当てられます。マネージド ヒープにエスケープすることはできません。 これを確実にするために、コンパイラでは次のように ref struct 型の使用が制限されます。

  • ref struct を配列の要素型にすることはできません。
  • ref struct をクラスまたは非 ref struct のフィールドの宣言型にすることはできません。
  • ref struct ではインターフェイスを実装できません。
  • ref structSystem.ValueType または System.Object にボックス化することはできません。
  • ref struct を型引数にすることはできません。
  • ref struct 変数をラムダ式またはローカル関数でキャプチャすることはできません。
  • ref struct 変数を async メソッド内で使用することはできません。 ただし、同期メソッドでは ref struct 変数を使用できます (Task または Task<TResult> を返すメソッドなど)。
  • ref struct 変数を反復子内で使用することはできません。

破棄可能な ref struct を定義できます。 そのためには、ref struct破棄可能なパターンに適合するようにします。 つまり、これには、アクセス可能かつパラメーターなしの、void の戻り値型を持つ、インスタンス Dispose メソッドが含まれます。 using ステートメントまたは宣言は、破棄可能な ref struct のインスタンスと共に使用できます。

通常、ref struct 型のデータ メンバーも含む型が必要な場合は、ref struct 型を定義します。

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

ref structreadonly として宣言するには、型宣言内で 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 structref フィールドを宣言できます。

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> インスタンスは参照先のストレージのコピーを回避できます。

C# 言語仕様

詳細については、「C# 言語仕様」の次のセクションを参照してください。

ref フィールドの詳細については、「低レベル構造体の機能強化」の提案メモを参照してください。

関連項目