Struct biasa masih boleh pindah ke heap, misalnya saat di-boxing atau disimpan sebagai field class. Ada kelompok struct yang tidak boleh berpindah tempat sedikit pun, karena data tersebut merujuk langsung ke ruang memori milik pihak lain. Tipe semacam itu diberi modifier ref, sehingga kita menyebutnya ref struct. Contoh nyata di .NET adalah ReadOnlySpan<char>: jendela baca ke memori string atau array tanpa menyalin isinya. Bab ini memberikan pengantar aturan yang menyertai tipe tersebut.

Contoh Utama: ReadOnlySpan<char> #

Contoh berikut memecah catatan belanja menjadi produk dan harga menggunakan ReadOnlySpan<char>. Seluruh pemotongan bekerja pada memori string asal, bukan pada salinan baru:

csharp
string catatan = "Susu 12000;Roti 15000";
ReadOnlySpan<char> isi = catatan.AsSpan();

int posisiPemisah = isi.IndexOf(';');
ReadOnlySpan<char> produk = isi.Slice(0, posisiPemisah);
ReadOnlySpan<char> harga = isi.Slice(posisiPemisah + 1);

Console.WriteLine(produk.ToString());
Console.WriteLine(harga.ToString());

ReadOnlySpan<char> potongan = "Belajar C#".AsSpan(0, 7);
Console.WriteLine(potongan.ToString());

Output yang Dihasilkan:

text
Susu 12000
Roti 15000
Belajar

Mari kita bedah baris demi baris:

  1. catatan.AsSpan(): method AsSpan membuat span yang menunjuk karakter-karakter string catatan; tidak ada satu pun karakter yang disalin.
  2. isi.IndexOf(';'): span mencari posisi pemisah di memori yang sama; hasilnya indeks karakter ;.
  3. isi.Slice(0, posisiPemisah): Slice menghasilkan span baru yang menunjuk sebagian memori string asal; lagi-lagi tanpa alokasi baru.
  4. produk.ToString(): penyalinan ke string baru baru terjadi di baris ini, ketika data benar-benar dibutuhkan sebagai string.
  5. "Belajar C#".AsSpan(0, 7): parameter kedua menyatakan panjang potongan; hasilnya tujuh karakter pertama, yaitu Belajar.

Aturan yang Menyertai ref struct #

Karena ref struct merujuk memori yang usianya terikat pada satu konteks eksekusi, compiler memberlakukan aturan ketat berikut:

  • Data tidak boleh berpindah ke heap: ref struct tidak dapat di-boxing dan tidak boleh disimpan sebagai field class biasa.
  • Data tidak boleh melewati batas await: method async tidak dapat menahan ref struct menyeberang penantian.
  • Data tidak boleh ditangkap oleh lambda maupun local function.
  • Ref struct lain hanya boleh disimpan sebagai anggota dari ref struct; class biasa tidak boleh memuatnya sebagai field maupun auto-property.

Dua pelanggaran pertama menghasilkan galat kompilasi nyata berikut:

text
error CS8345: Field or auto-implemented property cannot be of type 'ReadOnlySpan<char>' unless it is an instance member of a ref struct.
text
error CS4007: Instance of type 'System.ReadOnlySpan<char>' cannot be preserved across 'await' or 'yield' boundary.