Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Jest SpanOwner<T> to typ buforu tylko dla stosu, który wynajmuje z puli pamięci udostępnionej. Zasadniczo odzwierciedla funkcjonalność MemoryOwner<T>elementu , ale jako ref struct typ. Jest to szczególnie przydatne w przypadku krótkotrwałych, które są używane tylko w kodzie synchronicznym (które nie wymagają Memory<T> wystąpień), a także w pętli ścisłej, ponieważ tworzenie SpanOwner<T> wartości w ogóle nie będzie wymagać alokacji pamięci.
Interfejsy API platformy:
SpanOwner<T>,MemoryOwner<T>
Składnia
Te same podstawowe funkcje MemoryOwner<T> mają zastosowanie również do tego typu, z wyjątkiem tego, że jest to tylko stos struct, i fakt, że nie ma IMemoryOwner<T>interface implementacji, a także Memory<T> właściwość. Składnia jest praktycznie identyczna z składnią używaną z MemoryOwner<T> programem , z wyjątkiem różnic wymienionych powyżej.
Załóżmy na przykład, że mamy metodę, w której musimy przydzielić tymczasowy bufor o określonym rozmiarze (nazwijmy tę wartość length), a następnie użyjemy jej do wykonania jakiejś pracy. Po pierwsze, nieefektywna wersja może wyglądać następująco:
byte[] buffer = new byte[length];
// Use buffer here
Nie jest to idealne rozwiązanie, ponieważ przydzielamy nowy bufor za każdym razem, gdy ten kod jest używany, a następnie natychmiast go wyrzuca (jak wspomniano również w MemoryOwner<T> dokumentacji), co wywiera większą presję na moduł odśmiecania pamięci. Możemy zoptymalizować powyższy kod przy użyciu polecenia ArrayPool<T>:
// Using directive to access the ArrayPool<T> type
using System.Buffers;
int[] buffer = ArrayPool<int>.Shared.Rent(length);
try
{
// Slice the span, as it might be larger than the requested size
Span<int> span = buffer.AsSpan(0, length);
// Use the span here
}
finally
{
ArrayPool<int>.Shared.Return(buffer);
}
Powyższy kod wynajmuje bufor z puli tablic, ale jest bardziej szczegółowy i podatny na błędy: musimy zachować ostrożność z try/finally blokiem, aby upewnić się, że zawsze zwraca wynajęty bufor do puli. Możemy go ponownie napisać przy użyciu SpanOwner<T> typu , w następujący sposób:
// Be sure to include this using at the top of the file:
using Microsoft.Toolkit.HighPerformance.Buffers;
using SpanOwner<int> buffer = SpanOwner<int>.Allocate(length);
Span<int> span = buffer.Span;
// Use the span here, no slicing necessary
Wystąpienie SpanOwner<T> wewnętrznie wynajmuje tablicę i zajmie się zwróceniem jej do puli, gdy wykracza poza zakres. Nie musimy już używać try/finally bloku, ponieważ kompilator języka C# doda to automatycznie podczas rozszerzania tej using instrukcji. W związku z tym SpanOwner<T> typ może być postrzegany jako uproszczona otoka interfejsów ArrayPool<T> API, co sprawia, że są one zarówno bardziej kompaktowe, jak i łatwiejsze do użycia, zmniejszając ilość kodu, który należy zapisać w celu prawidłowego wynajmu i usuwania krótkotrwałych. Możesz zobaczyć, jak użycie SpanOwner<T> sprawia, że kod jest znacznie krótszy i prostszy.
Uwaga
Ponieważ jest to typ tylko stosu, opiera się na wzorcu typu duck wprowadzonym IDisposable w języku C# 8. Pokazano to w powyższym przykładzie: SpanOwner<T> typ jest używany w using bloku, pomimo faktu, że typ w ogóle nie implementuje interfejsu IDisposable i nigdy nie jest w polu. Funkcjonalność jest taka sama: gdy tylko bufor wykracza poza zakres, jest on automatycznie usuwany. Interfejsy API w SpanOwner<T> programie opierają się na tym wzorcu dla dodatkowej wydajności: zakładają, że bufor bazowy nigdy nie zostanie usunięty, o ile SpanOwner<T> typ jest w zakresie i nie wykonują dodatkowych kontroli, które są wykonywane w MemoryOwner<T> celu zapewnienia, że bufor jest w rzeczywistości nadal dostępny przed zwróceniem Memory<T> wystąpienia lub Span<T> z niego. W związku z tym ten typ powinien być zawsze używany z blokiem lub wyrażeniem using . Nie spowoduje to zwrócenia bazowego buforu do puli udostępnionej. Technicznie można to również osiągnąć, ręcznie wywołując Dispose typ (który nie wymaga języka C# 8), ale jest podatny na SpanOwner<T> błędy i dlatego nie jest to zalecane.
Przykłady
.NET Community Toolkit