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:
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:
Susu 12000
Roti 15000
BelajarMari kita bedah baris demi baris:
catatan.AsSpan(): methodAsSpanmembuat span yang menunjuk karakter-karakter stringcatatan; tidak ada satu pun karakter yang disalin.isi.IndexOf(';'): span mencari posisi pemisah di memori yang sama; hasilnya indeks karakter;.isi.Slice(0, posisiPemisah):Slicemenghasilkan span baru yang menunjuk sebagian memori string asal; lagi-lagi tanpa alokasi baru.produk.ToString(): penyalinan ke string baru baru terjadi di baris ini, ketika data benar-benar dibutuhkan sebagai string."Belajar C#".AsSpan(0, 7): parameter kedua menyatakan panjang potongan; hasilnya tujuh karakter pertama, yaituBelajar.
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:
error CS8345: Field or auto-implemented property cannot be of type 'ReadOnlySpan<char>' unless it is an instance member of a ref struct.error CS4007: Instance of type 'System.ReadOnlySpan<char>' cannot be preserved across 'await' or 'yield' boundary.