次の方法で共有


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

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

  • ref struct を配列の要素型にすることはできません。
  • ref struct をクラスまたは非 ref struct のフィールドの宣言型にすることはできません。
  • ref structSystem.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 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 以降では、次の例に示すように、refref 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 フィールドの詳細については、「低レベル構造体の機能強化」の提案メモを参照してください。

関連項目