Kelas SpanOwner<T>

Kelas SpanOwner<T> ini adalah jenis buffer khusus tumpukan yang menyewa buffer dari kumpulan memori bersama. Ini pada dasarnya mencerminkan fungsionalitas MemoryOwner<T>, namun sebagai jenis ref struct. Fungsi ini sangat berguna untuk buffer yang berumur pendek yang hanya digunakan dalam kode sinkron (yang tidak memerlukan instans Memory<T>), serta kode yang dijalankan dalam perulangan ketat. Membuat SpanOwner<T> nilai tidak memerlukan alokasi memori.

API Platform:SpanOwner<T>, MemoryOwner<T>

Sintaks

Fitur inti MemoryOwner<T> yang sama berlaku untuk jenis ini juga, kecuali bahwa itu hanya untuk stack struct. Ini juga tidak memiliki IMemoryOwner<T>interface implementasi, serta Memory<T> properti. Sintaks hampir identik dengan sintaks yang digunakan dengan MemoryOwner<T>, kecuali untuk perbedaan yang disebutkan sebelumnya.

Misalnya, Anda memiliki metode di mana Anda perlu mengalokasikan buffer sementara dengan ukuran tertentu (mari kita panggil nilai lengthini ), lalu gunakan untuk melakukan beberapa pekerjaan. Versi pertama yang tidak efisien mungkin terlihat seperti ini:

byte[] buffer = new byte[length];

// Use buffer here

Versi ini tidak ideal karena mengalokasikan buffer baru setiap kali Anda menggunakan kode ini, dan kemudian segera membuangnya. Pendekatan ini memberikan lebih banyak tekanan pada pengumpul sampah. Anda dapat mengoptimalkan kode sebelumnya dengan menggunakan 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);
}

Kode sebelumnya menyewa buffer dari kumpulan array, tetapi lebih verbose dan rawan kesalahan. Anda harus berhati-hati dengan blok try/finally untuk memastikan Anda selalu mengembalikan buffer yang dipinjam ke kumpulan. Anda dapat menulis ulang dengan menggunakan jenis SpanOwner<T>, seperti ini:

// 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

Instance SpanOwner<T> secara internal meminjam array, dan mengurus pengembaliannya ke kumpulan ketika tidak lagi digunakan. Anda juga tidak perlu lagi menggunakan try/finally blok, karena kompiler C# menambahkannya secara otomatis ketika memperluas using pernyataan tersebut. Dengan demikian, Anda dapat melihat jenis SpanOwner<T> sebagai pembungkus ringan di sekitar API ArrayPool<T>. Ini membuat mereka lebih ringkas dan lebih mudah digunakan, mengurangi jumlah kode yang perlu Anda tulis untuk menyewa dan membuang buffer yang berumur pendek dengan benar. Anda dapat melihat cara menggunakan SpanOwner<T> membuat kode jauh lebih pendek dan lebih mudah.

Catatan

Karena ini adalah jenis hanya tumpukan, ia bergantung pada pola duck-typed IDisposable yang diperkenalkan dengan C# 8. Pola tersebut ditampilkan dalam sampel sebelumnya: tipe SpanOwner<T> digunakan dalam blok using meskipun tipe tersebut tidak mengimplementasikan antarmuka IDisposable sama sekali, dan juga tidak pernah dipetakan ke tipe kotak. Fungsionalitasnya sama: segera setelah buffer keluar dari cakupan, buffer tersebut secara otomatis dikeluarkan. API di SpanOwner<T> mengandalkan pola ini untuk performa ekstra: mereka mengasumsikan bahwa buffer dasar tidak pernah dibuang selama tipe SpanOwner<T> berada dalam cakupan. Mereka tidak melakukan pemeriksaan tambahan seperti yang dilakukan di dalam MemoryOwner<T> untuk memastikan buffer tersebut tetap tersedia sebelum mengembalikan sebuah instans Memory<T> atau Span<T> darinya. Dengan demikian, selalu gunakan tipe ini dengan using blok atau ekspresi. Tidak melakukannya menyebabkan buffer yang mendasar tidak dikembalikan ke kumpulan bersama. Secara teknis, Anda dapat mencapai hasil yang sama dengan memanggil Dispose pada tipe SpanOwner<T> secara manual (yang tidak memerlukan C# 8), tetapi pendekatan tersebut rawan kesalahan dan karenanya tidak disarankan.

Contoh

Anda dapat menemukan lebih banyak contoh dalam pengujian unit.