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 enasync
metod. Från och med C# 13 kan enref struct
variabel inte användas i samma block somawait
uttrycket i enasync
metod. Du kan dock användaref 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# 13ref struct
kan typer ochref
lokalbefolkningen användas i iteratorer, förutsatt att de inte finns i kodsegment med -instruktionenyield return
. - Före C# 13 kan en
ref struct
inte implementera gränssnitt. Från och med C# 13 kan enref
struct implementera gränssnitt, men måste följa referenssäkerhetsreglerna . En typ kan till exempelref 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 ettref struct
vara typargumentet när typparametern angerallows 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 (readonly
modifieraren 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 eninit
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 eninit
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 IDisposable på ref 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 enref 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 struct
om : 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å .