ref strukturtyper (C#-referens)

Du kan använda ref modifieraren i deklarationen av en strukturtyp. Instanser av en ref struct typ allokeras i stacken och kan inte fly till den hanterade heapen. För att säkerställa att kompilatorn begränsar användningen av ref struct typer enligt följande:

  • A ref struct kan inte vara elementtypen för en matris.
  • A ref struct kan inte vara en deklarerad typ av ett fält i en klass eller en icke-ref struct.
  • A ref struct kan inte boxas till System.ValueType eller System.Object.
  • En ref struct variabel kan inte avbildas i ett lambda-uttryck eller en lokal funktion.
  • Före C# 13 ref struct kan variabler inte användas i en async metod. Från och med C# 13 kan en ref struct variabel inte användas i samma block som await uttrycket i en async metod. Du kan dock använda ref struct variabler i synkrona metoder, till exempel i metoder som returnerar Task eller Task<TResult>.
  • Före C# 13 kan en ref struct variabel inte användas i iteratorer. Från och med C# 13 ref struct kan typer och ref lokalbefolkningen användas i iteratorer, förutsatt att de inte finns i kodsegment med -instruktionen yield return .
  • Före C# 13 kan en ref struct inte implementera gränssnitt. Från och med C# 13 kan en ref struct implementera gränssnitt, men måste följa referenssäkerhetsreglerna . En typ kan till exempel ref struct inte konverteras till gränssnittstypen eftersom det kräver en boxningskonvertering.
  • Före C# 13 kan en ref struct inte vara ett typargument. Från och med C# 13 kan ett ref struct vara typargumentet när typparametern anger allows ref struct i - where satsen.

Vanligtvis definierar du en ref struct typ när du behöver en typ som även innehåller datamedlemmar av ref struct typer:

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

Om du vill deklarera en ref struct som kombinerar readonly du och ref modifierarna i typdeklarationen (readonlymodifieraren måste komma före ref modifierarenreadonly):

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

I .NET är System.Span<T> System.ReadOnlySpan<T>och ref struct .

ref Fält

Från och med C# 11 kan du deklarera ett ref fält i ett ref struct, som följande exempel visar:

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

Ett ref fält kan ha värdet null . Unsafe.IsNullRef<T>(T) Använd metoden för att avgöra om ett ref fält är null.

Du kan tillämpa readonly modifieraren på ett ref fält på följande sätt:

  • readonly ref: Du kan återtilldela ett sådant fält med operatorn = ref endast inuti en konstruktor eller en init accessor. Du kan tilldela ett värde med operatorn = när som helst som tillåts av fältåtkomstmodifieraren.
  • ref readonly: Du kan när som helst inte tilldela ett värde med operatorn = till ett sådant fält. Du kan dock återtilldela ett fält med operatorn = ref .
  • readonly ref readonly: Du kan bara återtilldela ett sådant fält i en konstruktor eller en init accessor. När som helst kan du inte tilldela ett värde till fältet.

Kompilatorn ser till att en referens som lagras i ett ref fält inte överlever sina referenser.

Funktionen ref fält möjliggör en säker implementering av typer som System.Span<T>:

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

    // Omitted for brevity...
}

Typen Span<T> lagrar en referens genom vilken den kommer åt sammanhängande element i minnet. Med hjälp av en referens kan en Span<T> instans undvika att kopiera lagringen som den refererar till.

Engångsmönstret

Du kan definiera en disponibel ref struct. För att göra det, se till att ett ref struct passar disponibelt mönster. Den har alltså en instansmetod Dispose som är tillgänglig, parameterlös och har en void returtyp. Du kan använda instruktionen eller deklarationen med en instans av en disponibel ref struct.

Från och med C# 13 kan du även implementera typerna IDisposableref struct . Överlagringsupplösning föredrar dock engångsmönstret jämfört med gränssnittsmetoden. Kompilatorn matchar en IDisposable.Dispose metod som endast innehåller en lämplig Dispose metod som inte hittas.

Begränsningar för ref struct typer som implementerar ett gränssnitt

Dessa begränsningar säkerställer att en ref struct typ som implementerar ett gränssnitt följer de nödvändiga referenssäkerhetsreglerna .

  • En ref struct kan inte konverteras till en instans av ett gränssnitt som implementeras. Den här begränsningen inkluderar implicit konvertering när du använder en ref struct typ som argument när parametern är en gränssnittstyp. Konverteringen resulterar i en boxningskonvertering, vilket strider mot referenssäkerheten.
  • En ref struct som implementerar ett gränssnitt måste implementera alla gränssnittsmedlemmar. ref struct Måste implementera medlemmar där gränssnittet innehåller en standardimplementering.

Kompilatorn tillämpar dessa begränsningar. Om du skriver ref struct typer som implementerar gränssnitt kan varje ny uppdatering innehålla nya standardgränssnittsmedlemmar. Programmet kompileras inte förrän du har angett en implementering för dessa nya metoder.

Viktigt!

En ref struct som implementerar ett gränssnitt innehåller potentialen för senare källbrytande och binärt icke-bakåtkompatibla ändringar. Pausen inträffar om en ref struct implementerar ett gränssnitt som definierats i en annan sammansättning och den sammansättningen tillhandahåller en uppdatering som lägger till standardmedlemmar i gränssnittet.

Källbrytningen inträffar när du kompilera ref structom : Den måste implementera den nya medlemmen, även om det finns en standardimplementering.

Binärbrytningen sker om du uppgraderar den externa sammansättningen utan att kompilera ref struct om typen och den uppdaterade koden anropar standardimplementeringen av den nya metoden. Körningen utlöser ett undantag när standardmedlemmen används.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Mer information om ref fält finns i förslag på förbättringar på låg nivå .

Se även