Delen via


ref structuurtypen (C#-verwijzing)

U kunt de ref wijzigingsfunctie gebruiken in de declaratie van een structuurtype. Exemplaren van een ref struct type worden toegewezen aan de stack en kunnen niet ontsnappen aan de beheerde heap. Om ervoor te zorgen dat de compiler het gebruik van ref struct typen als volgt beperkt:

  • Een ref struct kan niet het elementtype van een matrix zijn.
  • Een ref struct kan geen gedeclareerd type van een veld van een klasse of een niet-ref struct.
  • Een ref struct kan niet worden geboksd aan System.ValueType of System.Object.
  • Een ref struct variabele kan niet worden vastgelegd in een lambda-expressie of een lokale functie.
  • Voor C# 13ref struct kunnen variabelen niet worden gebruikt in een async methode. Vanaf C# 13 kan een ref struct variabele niet worden gebruikt in hetzelfde blok als de await expressie in een async methode. U kunt echter variabelen gebruiken ref struct in synchrone methoden, bijvoorbeeld in methoden die retourneren Task of Task<TResult>.
  • Voor C# 13 kan een ref struct variabele niet worden gebruikt in iterators. Vanaf C# 13 ref struct kunnen typen en ref lokale bevolking worden gebruikt in iterators, mits ze zich niet in codesegmenten met de yield return instructie bevindt.
  • Voor C# 13 ref struct kunnen interfaces niet worden geïmplementeerd. Vanaf C# 13 kan een ref struct interfaces implementeren, maar moet voldoen aan de veiligheidsregels van ref. Een type kan bijvoorbeeld ref struct niet worden geconverteerd naar het interfacetype omdat hiervoor een boksconversie is vereist.
  • Voor C# 13 kan een ref struct typeargument niet zijn. Vanaf C# 13 kan een ref struct typeargument zijn wanneer de typeparameter de component in de allows ref struct component where opgeeft.

Normaal gesproken definieert u een ref struct type wanneer u een type nodig hebt dat ook gegevensleden van ref struct typen bevat:

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

Als u een als readonlywilt ref struct declareren, combineert u de readonly en ref modifiers in de typedeclaratie (de readonly modifier moet vóór de ref wijzigingsfunctie komen):

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 zijn System.Span<T> System.ReadOnlySpan<T>en ref struct .

ref Velden

Vanaf C# 11 kunt u een ref veld in een ref structdeclareren, zoals in het volgende voorbeeld wordt weergegeven:

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

Een ref veld kan de null waarde hebben. Gebruik de Unsafe.IsNullRef<T>(T) methode om te bepalen of een ref veld is null.

U kunt de readonly wijzigingsfunctie op een ref veld op de volgende manieren toepassen:

  • readonly ref: U kunt een dergelijk veld opnieuw toewijzen aan de = ref operator alleen binnen een constructor of een init accessor. U kunt een waarde toewijzen aan de = operator op elk gewenst moment dat is toegestaan door de wijzigingsfunctie voor veldtoegang.
  • ref readonly: U kunt op enig moment geen waarde met de = operator toewijzen aan een dergelijk veld. U kunt echter een veld opnieuw toewijzen met de = ref operator.
  • readonly ref readonly: U kunt een dergelijk veld alleen opnieuw toewijzen in een constructor of een init accessor. U kunt op elk moment geen waarde aan het veld toewijzen.

De compiler zorgt ervoor dat een verwijzing die is opgeslagen in een ref veld, de referent niet overleeft.

De ref functie velden maakt een veilige implementatie van typen mogelijk, zoals System.Span<T>:

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

    // Omitted for brevity...
}

Het Span<T> type slaat een verwijzing op waarmee deze toegang heeft tot de aaneengesloten elementen in het geheugen. Met het gebruik van een verwijzing kan een Span<T> exemplaar voorkomen dat de opslag waarnaar wordt verwezen, wordt gekopieerd.

Het wegwerppatroon

U kunt een wegwerp ref structdefiniëren. Om dat te doen, moet u ervoor zorgen dat een ref struct past bij het wegwerppatroon. Dat wil gezegd, het heeft een exemplaarmethode Dispose , die toegankelijk, parameterloos is en een void retourtype heeft. U kunt de using-instructie of declaratie gebruiken met een exemplaar van een wegwerp.ref struct

Vanaf C# 13 kunt u ook de IDisposable typen ref struct implementeren. Overbelastingsresolutie geeft echter de voorkeur aan het wegwerppatroon aan de interfacemethode. De compiler wordt alleen omgezet in een IDisposable.Dispose methode die alleen geschikt is voor een geschikte Dispose methode.

Beperkingen voor ref struct typen die een interface implementeren

Deze beperkingen zorgen ervoor dat een ref struct type dat een interface implementeert, voldoet aan de noodzakelijke ref-veiligheidsregels .

  • Een ref struct kan niet worden geconverteerd naar een instantie van een interface die wordt geïmplementeerd. Deze beperking omvat de impliciete conversie wanneer u een ref struct type als argument gebruikt wanneer de parameter een interfacetype is. De conversie resulteert in een boksconversie, die de veiligheid van ref schendt.
  • Een ref struct die een interface implementeert, moet alle interfaceleden implementeren. De ref struct implementatie moet leden implementeren waarbij de interface een standaard implementatie bevat.

De compiler dwingt deze beperkingen af. Als u typen schrijft ref struct die interfaces implementeren, kan elke nieuwe update nieuwe standaardinterfaceleden bevatten. Totdat u een implementatie voor deze nieuwe methoden opgeeft, wordt uw toepassing niet gecompileerd.

Belangrijk

Een ref struct die een interface implementeert, omvat het potentieel voor latere wijzigingen die fouten veroorzaken door bronnen en binaire fouten. De onderbreking treedt op als een ref struct interface wordt geïmplementeerd die is gedefinieerd in een andere assembly en die assembly een update biedt waarmee standaardleden aan die interface worden toegevoegd.

Het brononderbreking vindt plaats wanneer u het ref structnieuwe lid opnieuw compileert, ook al is er een standaard implementatie.

Het binaire einde vindt plaats als u de externe assembly bijwerkt zonder het ref struct type opnieuw te compileren en de bijgewerkte code de standaard implementatie van de nieuwe methode aanroept. De runtime genereert een uitzondering wanneer het standaardlid wordt geopend.

C#-taalspecificatie

Zie de volgende secties van de C#-taalspecificatie voor meer informatie:

Zie de offertenota voor structverbeteringen op laag niveau voor meer informatie over ref velden.

Zie ook