Udostępnij za pośrednictwem


ref typy struktury (odwołanie w C#)

Modyfikator można użyć ref w deklaracji typu struktury. ref struct Wystąpienia typu są przydzielane na stosie i nie mogą uciec do zarządzanego sterta. Aby upewnić się, że kompilator ogranicza użycie ref struct typów w następujący sposób:

  • Nie ref struct można być typem elementu tablicy.
  • Nie ref struct można zadeklarować typu pola klasy lub innej klasyref struct.
  • ref struct Nie można poleceć do System.ValueType lub System.Object.
  • Nie ref struct można przechwycić zmiennej w wyrażeniu lambda lub funkcji lokalnej.
  • Przed C# 13 ref struct nie można używać zmiennych w metodzie async . Począwszy od języka C# 13, zmienna ref struct nie może być używana w tym samym bloku co await wyrażenie w metodzie async . Można jednak używać ref struct zmiennych w metodach synchronicznych, na przykład w metodach, które zwracają Task lub Task<TResult>.
  • Przed C# 13 nie można używać zmiennej ref struct w iteratorach. Począwszy od języka C# 13, ref struct typy i ref ustawienia lokalne mogą być używane w iteratorach, pod warunkiem, że nie są one w segmentach kodu z instrukcją yield return .
  • Przed C# 13 ref struct nie można zaimplementować interfejsów. Począwszy od języka C# 13, ref struktura może implementować interfejsy, ale musi być zgodna z regułami bezpieczeństwa ref. Na przykład nie można przekonwertować typu na typ interfejsu, ref struct ponieważ wymaga to konwersji boxingu.
  • Przed C# 13 ref struct nie może być argumentem typu. Począwszy od języka C# 13, argument może ref struct być argumentem typu, gdy parametr typu określa allows ref struct wartość w klauzuli where .

Zazwyczaj typ jest definiowany ref struct , gdy potrzebujesz typu, który zawiera również elementy członkowskie danych typów ref struct :

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

Aby zadeklarować ref struct element jako readonly, połącz readonly modyfikatory i ref w deklaracji typu ( readonly modyfikator musi pojawić się przed ref modyfikatorem):

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

Na platformie .NET przykłady elementów ref struct to System.Span<T> i System.ReadOnlySpan<T>.

ref Pola

Począwszy od języka C# 11, można zadeklarować ref pole w elemecie ref struct, jak pokazano w poniższym przykładzie:

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 może mieć null wartość . Unsafe.IsNullRef<T>(T) Użyj metody , aby określić, czy ref pole ma wartość null.

Modyfikator można zastosować readonly do ref pola w następujący sposób:

  • readonly ref: Można ponownie przypisać takie pole za pomocą = ref operatora tylko wewnątrz konstruktora init lub metody dostępu. Wartość można przypisać operatorowi = w dowolnym momencie dozwolonym przez modyfikator dostępu do pól.
  • ref readonly: W żadnym momencie nie można przypisać wartości operatorowi = do takiego pola. Można jednak ponownie przypisać pole za = ref pomocą operatora .
  • readonly ref readonly: Można ponownie przypisać tylko takie pole w konstruktorze lub init metodzie dostępu. W żadnym momencie nie można przypisać wartości do pola.

Kompilator gwarantuje, że odwołanie przechowywane w ref polu nie przeżyje jego odwołania.

Funkcja ref pól umożliwia bezpieczną implementację typów, takich jak System.Span<T>:

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

    // Omitted for brevity...
}

Typ Span<T> przechowuje odwołanie, za pomocą którego uzyskuje dostęp do ciągłych elementów w pamięci. Użycie odwołania umożliwia Span<T> wystąpieniu uniknięcie kopiowania magazynu, do których się odwołuje.

Wzorzec jednorazowy

Można zdefiniować jednorazowy ref structelement . W tym celu upewnij się, że element ref struct pasuje do jednorazowego wzorca. Oznacza to, że ma metodę wystąpienia Dispose , która jest dostępna, bez parametrów i ma typ zwracany void . Możesz użyć instrukcji using lub deklaracji z wystąpieniem jednorazowego ref struct.

Począwszy od języka C# 13, można również zaimplementować typy IDisposable dla typów ref struct . Jednak rozdzielczość przeciążenia preferuje wzorzec jednorazowego dla metody interfejsu. Kompilator rozpoznaje metodę IDisposable.Dispose tylko whan odpowiednia Dispose metoda nie zostanie znaleziona.

Ograniczenia dotyczące ref struct typów implementujących interfejs

Te ograniczenia zapewniają, że ref struct typ implementujący interfejs przestrzega niezbędnych reguł bezpieczeństwa ref.

  • ref struct Nie można przekonwertować obiektu na wystąpienie implementowanego interfejsu. To ograniczenie obejmuje niejawną ref struct konwersję w przypadku użycia typu jako argumentu, gdy parametr jest typem interfejsu. Konwersja powoduje konwersję boksu, która narusza bezpieczeństwo ref.
  • Element ref struct implementujący interfejs musi implementować wszystkie elementy członkowskie interfejsu. Element ref struct musi implementować elementy członkowskie, w których interfejs zawiera domyślną implementację.

Kompilator wymusza te ograniczenia. W przypadku pisania ref struct typów implementujących interfejsy każda nowa aktualizacja może zawierać nowe domyślne elementy członkowskie interfejsu. Dopóki nie udostępnisz implementacji dla tych nowych metod, aplikacja nie zostanie skompilowana.

Ważne

Element ref struct implementujący interfejs zawiera potencjał późniejszych zmian powodujących niezgodność źródła i niezgodność binarną. Przerwa występuje, jeśli ref struct element implementuje interfejs zdefiniowany w innym zestawie, a zestaw udostępnia aktualizację, która dodaje domyślne elementy członkowskie do tego interfejsu.

Przerwa źródłowa występuje podczas ponownego ref structkompilowania elementu : Musi zaimplementować nowy element członkowski, mimo że istnieje domyślna implementacja.

Awaria binarna ma miejsce w przypadku uaktualnienia zestawu zewnętrznego bez ponownego skompilowania ref struct typu , a zaktualizowany kod wywołuje domyślną implementację nowej metody. Środowisko uruchomieniowe zgłasza wyjątek, gdy jest uzyskiwany dostęp do domyślnego elementu członkowskiego.

specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz następujące sekcje specyfikacji języka C#:

Aby uzyskać więcej informacji na temat ref pól, zobacz notatkę o propozycji ulepszenia struktury niskiego poziomu.

Zobacz też