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 metodzieasync
. Począwszy od języka C# 13, zmiennaref struct
nie może być używana w tym samym bloku coawait
wyrażenie w metodzieasync
. 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 iref
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żeref struct
być argumentem typu, gdy parametr typu określaallows ref struct
wartość w klauzuliwhere
.
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 konstruktorainit
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 lubinit
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 struct
element . 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. Elementref 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 struct
kompilowania 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.