Method Substring mengambil potongan teks dengan menyalin karakter-karakternya ke objek string baru. Pada data kecil, biaya salinan ini tidak terasa; pada pengolahan teks bervolume besar, salinan menumpuk dan membebani garbage collector. Tipe ReadOnlySpan<char> menawarkan jalan lain: span memandang rentang karakter yang sudah ada tanpa menyalin apa pun. Bab ini memperkenalkan pemakaiannya pada string di level pengantar.

ReadOnlySpan<char> pada String #

Method AsSpan mengubah string menjadi ReadOnlySpan<char>. Span mendukung properti Length, pengindeksan, dan pemotongan lewat AsSpan(start, length) — semuanya tanpa alokasi baru:

csharp
string pesanan = "Kopi Susu Gula Aren";

ReadOnlySpan<char> semua = pesanan.AsSpan();
Console.WriteLine(semua.Length);
Console.WriteLine(semua[5]);

Console.WriteLine(pesanan.AsSpan(0, 4).ToString());
Console.WriteLine(pesanan.AsSpan(10).ToString());
Console.WriteLine(pesanan.AsSpan(5, 4).SequenceEqual("Susu".AsSpan()));

Output yang Dihasilkan:

text
19
S
Kopi
Gula Aren
True

Mari kita telaah baris demi baris:

  1. Baris 3 (pesanan.AsSpan()): Span memandang seluruh 19 karakter string; tidak ada salinan yang dibuat, hanya alamat dan panjang yang dicatat.
  2. Baris 5 (semua[5]): Pengindeksan membaca karakter pada posisi 5 langsung dari string asal, yaitu S.
  3. Baris 7-8 (AsSpan(0, 4) dan AsSpan(10)): Pemotongan hanya menggeser jendela pandang; ToString() baru membuat string saat hasilnya benar-benar dicetak.
  4. Baris 9 (SequenceEqual): Perbandingan karakter berjalan di atas span tanpa menyalin; potongan posisi 5 sepanjang 4 karakter sama dengan "Susu", sehingga hasilnya True.

Buffer di Stack dengan stackalloc #

Selain membaca data yang sudah ada, span juga bisa menampung buffer sementara lewat stackalloc. Alokasinya berada di stack dan dibersihkan otomatis saat method selesai, tanpa campur tangan garbage collector:

csharp
Span<char> inisial = stackalloc char[3];
inisial[0] = 'K';
inisial[1] = 'S';
inisial[2] = 'G';
Console.WriteLine(new string(inisial));

Output yang Dihasilkan:

text
KSG

stackalloc char[3] menyediakan tiga sel karakter di stack, dan setiap sel diisi lewat indeks. Konversi new string(inisial) hanya dilakukan sekali di akhir, saat teks benar-benar dibutuhkan sebagai string.

Memory<T> untuk Skenario Async #

Span<T> hidup di stack sehingga tidak boleh disimpan di field class maupun dipakai di dalam method async. Tipe Memory<T> menjadi jembatannya: semantiknya mirip span, tetapi boleh disimpan dan dilewatkan ke operasi asinkron:

csharp
ReadOnlyMemory<char> memori = pesanan.AsMemory(10, 4);
Console.WriteLine(memori.Span.ToString());

Output yang Dihasilkan:

text
Gula

AsMemory(10, 4) menandai rentang empat karakter mulai indeks 10. Properti Span pada Memory<char> mengembalikan span yang bisa dibaca kapan pun rentangnya dibutuhkan, dan pencetakan menampilkan Gula.