ref-Strukturtypen (C#-Referenz)

Sie können bei der Deklaration eines Strukturtyps den ref-Modifizierer verwenden. Instanzen eines ref struct-Typs werden auf dem Stapel zugeordnet und können nicht in den verwalteten Heap überwechseln. Der Compiler grenzt die Nutzung von ref struct-Typen wie folgt ein, um dies sicherzustellen:

  • Eine ref struct kann nicht der Elementtyp eines Arrays sein.
  • Eine ref struct kann kein deklarierter Typ eines Felds einer Klasse oder einer ref struct-fremden Struktur sein.
  • Eine ref struct kann keine Schnittstellen implementieren.
  • Für eine ref struct kann kein Boxing in System.ValueType oder System.Object durchgeführt werden.
  • Eine ref struct kann kein Typargument sein.
  • Eine ref struct-Variable kann nicht von einem Lambdaausdruck oder einer lokalen Funktion erfasst werden.
  • Eine ref struct-Variable kann nicht in einer async-Methode verwendet werden. Sie können ref struct-Variablen jedoch in synchronen Methoden verwenden, z. B. in solchen, die Task oder Task<TResult> zurückgeben.
  • Eine ref struct-Variable kann nicht in Iteratoren verwendet werden.

Sie können eine verwerfbare ref structdefinieren. Stellen Sie dazu sicher, dass eine ref struct dem Dispose-Muster entspricht. Das heißt, sie umfasst eine Instanzmethode Dispose, auf die zugegriffen werden kann, die parameterlos ist und einen Rückgabetyp void aufweist. Sie können die using-Anweisung oder -Deklaration mit einer Instanz einer verwerfbaren ref struct verwenden.

In der Regel definieren Sie einen ref struct-Typ, wenn Sie einen Typ benötigen, der außerdem Datenmember von ref struct-Typen enthält:

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

Kombinieren Sie die readonly- und ref-Modifizierer in der Typdeklaration (der readonly-Modifizierer muss vor dem ref-Modifizierer stehen), um eine ref struct als readonly zu deklarieren:

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; }
}

In .NET sind System.Span<T> und System.ReadOnlySpan<T> Beispiele für eine ref struct.

ref-Felder

Ab C# 11 können Sie ein ref-Feld in einer ref struct deklarieren, wie im folgenden Beispiel gezeigt:

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;
    }
}

Ein ref-Feld kann den Wert null aufweisen. Verwenden Sie die Unsafe.IsNullRef<T>(T)-Methode, um zu bestimmen, ob ein ref-Feld null ist.

Sie können den readonly-Modifizierer wie folgt auf ein ref-Feld anwenden:

  • readonly ref: Sie können ein solches Feld mit dem = ref-Operator nur innerhalb eines Konstruktors oder einer init-Zugriffsmethodeneu als Verweis zuweisen. Sie können mit dem =-Operator an jedem beliebigen Punkt einen Wert zuweisen, der durch den Feldzugriffsmodifizierer zugelassen wird.
  • ref readonly: An keinem Punkt können Sie einem solchen Feld einen Wert mit dem =-Operator zuweisen. Jedoch können Sie ein Feld mit dem = ref-Operator als Verweis erneut zuweisen.
  • readonly ref readonly: Sie können ein solches Feld nur in einem Konstruktor oder einer init-Zugriffsmethode als Verweis erneut zuweisen. An keinem Punkt können Sie dem Feld einen Wert zuweisen.

Der Compiler stellt sicher, dass ein in einem ref-Feld gespeicherter Verweis nicht länger vorhanden ist als das Element, auf das er verweist.

Das Feldfeature ref ermöglicht eine sichere Implementierung von Typen wie System.Span<T>:

public readonly ref struct Span<T>
{
    internal readonly ref T _reference;
    private readonly int _length;

    // Omitted for brevity...
}

Der Span<T>-Typ speichert einen Verweis, über den er auf die zusammenhängenden Elemente im Arbeitsspeicher zugreift. Durch die Verwendung eines Verweises muss eine Span<T>-Instanz den Speicher, auf den sie verweist, nicht kopieren.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen zu ref-Feldern finden Sie im Vorschlag zu Strukturverbesserungen auf niedriger Ebene.

Weitere Informationen