Sdílet prostřednictvím


ref typy struktur (referenční dokumentace jazyka C#)

Modifikátor můžete použít ref v deklaraci typu struktury. Instance typu ref struct se přidělují do zásobníku a nemůžou utéct ke spravované haldě. Aby se zajistilo, kompilátor omezuje použití typů ref struct následujícím způsobem:

  • A ref struct nemůže být typem prvku pole.
  • Nelze ref struct deklarovat typ pole třídy nebo jiného typuref struct.
  • A ref struct nemůže být v rámečku System.ValueType nebo System.Object.
  • Proměnnou ref struct nelze zachytit ve výrazu lambda ani v místní funkci.
  • Před jazykem C# 13 ref struct nelze proměnné použít v async metodě. Počínaje jazykem C# 13 nelze proměnnou ref struct použít ve stejném bloku jako await výraz v async metodě. Proměnné však můžete použít ref struct v synchronních metodách, například v metodách, které vrací Task nebo Task<TResult>.
  • Před C# 13 nelze proměnnou ref struct použít v iterátorech. Počínaje jazykem C# 13 ref struct je možné v iterátorech používat typy a ref místní hodnoty za předpokladu, že nejsou v segmentech kódu s příkazem yield return .
  • Před C# 13 ref struct nemůže implementovat rozhraní. Počínaje jazykem C# 13 ref může struktura implementovat rozhraní, ale musí dodržovat pravidla bezpečnosti ref. Například typ nelze převést na typ rozhraní, ref struct protože to vyžaduje převod boxingu.
  • Před jazykem ref struct C# 13 nemůže být argument typu. Počínaje jazykem C# 13 může být argument typu, ref struct pokud parametr typu určuje allows ref struct v klauzuli where .

Typ definujete ref struct obvykle v případě, že potřebujete typ, který zahrnuje i datové členy typů ref struct :

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

Chcete-li deklarovat ref struct jako readonly, zkombinujte readonly a ref modifikátory v deklaraci typu ( readonly modifikátor musí být před modifikátorem 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; }
}

V .NET jsou příklady ref struct a System.Span<T> System.ReadOnlySpan<T>.

ref pole

Počínaje jazykem C# 11 můžete deklarovat ref pole v následujícím příkladu ref 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;
    }
}

Pole ref může mít null hodnotu. Unsafe.IsNullRef<T>(T) Pomocí metody určete, zda ref je nullpole .

Modifikátor ref můžete u pole použít readonly následujícími způsoby:

  • readonly ref: Toto pole můžete znovu přiřadit pomocí operátoru = ref pouze uvnitř konstruktoru nebo přístupového objektuinit. Hodnotu s operátorem = můžete přiřadit v libovolném bodě povoleném modifikátorem přístupu k poli.
  • ref readonly: V žádném okamžiku nemůžete k takovému poli přiřadit hodnotu s = operátorem. Můžete ale znovu přiřadit pole pomocí operátoru = ref .
  • readonly ref readonly: Toto pole můžete znovu přiřadit pouze v konstruktoru nebo přístupovém objektu init . V žádném okamžiku nemůžete k poli přiřadit hodnotu.

Kompilátor zajistí, aby odkaz uložený v ref poli neobsáhl jeho odkaz.

Funkce ref polí umožňuje bezpečnou implementaci typů, jako System.Span<T>jsou:

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

    // Omitted for brevity...
}

Typ Span<T> ukládá odkaz, prostřednictvím kterého přistupuje k souvislým prvkům v paměti. Použití odkazu umožňuje Span<T> instanci zabránit kopírování úložiště, na které odkazuje.

Model na jedno použití

Můžete definovat uvolnitelné ref struct. Abyste to mohli udělat, ujistěte se, že vyhovuje jednorázovému ref struct vzoru. To znamená, že má metodu instance Dispose , která je přístupná, bez parametrů a má návratový void typ. Můžete použít příkaz using nebo deklaraci s instancí uvolnitelné ref struct.

Počínaje jazykem C# 13 můžete implementovat také typy IDisposable ref struct . Rozlišení přetížení však dává přednost jednorázovému vzoru pro metodu rozhraní. Kompilátor se překládá pouze na metodu IDisposable.Dispose , která je vhodná Dispose , nebyla nalezena.

Omezení pro ref struct typy, které implementují rozhraní

Tato omezení zajišťují, že ref struct typ, který implementuje rozhraní, dodržuje potřebná pravidla bezpečnosti ref.

  • A ref struct nelze převést na instanci rozhraní, které implementuje. Toto omezení zahrnuje implicitní převod při použití ref struct typu jako argumentu, pokud je parametr typem rozhraní. Výsledkem převodu je krabicový převod, který porušuje bezpečnost ref.
  • Rozhraní ref struct , které implementuje rozhraní , musí implementovat všechny členy rozhraní. Musí ref struct implementovat členy, kde rozhraní obsahuje výchozí implementaci.

Kompilátor vynucuje tato omezení. Pokud píšete ref struct typy, které implementují rozhraní, může každá nová aktualizace obsahovat nové výchozí členy rozhraní. Dokud pro tyto nové metody nezadáte implementaci, vaše aplikace se nezkompiluje.

Důležité

Implementace ref struct rozhraní zahrnuje potenciál pozdějších změn způsobujících chybu zdroje a binárních změn. K přerušení dojde, pokud ref struct implementuje rozhraní definované v jiném sestavení a toto sestavení poskytuje aktualizaci, která přidá do tohoto rozhraní výchozí členy.

K přerušení zdroje dojde při rekompilování ref struct: Musí implementovat nový člen, i když existuje výchozí implementace.

Binární přerušení nastane, pokud upgradujete externí sestavení bez rekompilování ref struct typu a aktualizovaný kód volá výchozí implementaci nové metody. Modul runtime vyvolá výjimku při přístupu výchozího člena.

specifikace jazyka C#

Další informace najdete v následujících částech specifikace jazyka C#:

Další informace o ref polích naleznete v návrhu vylepšení struktury nízké úrovně.

Viz také