Sebagian besar koleksi dalam aplikasi mengikuti pola yang sama: disusun sekali di awal, lalu dibaca ratusan ribu kali tanpa perubahan. Contohnya tabel ongkos kirim, daftar kota yang terdaftar, atau pemetaan kode pos. ImmutableDictionary<TKey, TValue> bisa menampung data semacam itu, tetapi strukturnya dirancang agar perubahan tetap murah, dan harga itu dibayar saat pencarian. .NET 8 menambahkan keluarga frozen collections: koleksi yang berhenti berubah secara permanen sehingga runtime bebas mengoptimalkan seluruh strukturnya untuk kecepatan baca.

Membekukan Koleksi #

Keduanya tersedia di namespace System.Collections.Frozen dan dibuat lewat method perluasan dari koleksi biasa:

  • ToFrozenDictionary(): mengubah IDictionary<TKey, TValue> menjadi FrozenDictionary<TKey, TValue>.
  • ToFrozenSet(): mengubah urutan item menjadi FrozenSet<T>.

Pembekuan satu kali memakan biaya lebih besar daripada membuat Dictionary<TKey, TValue> biasa, karena runtime menganalisis kunci dan memilih struktur internal yang paling sesuai. Setelah itu, operasi Contains, TryGetValue, dan pengaksesan indexer berjalan lebih cepat pada data besar. Nama frozen juga berarti tidak ada member penulisan sama sekali: koleksi hasilnya sekaligus immutable.

Contoh: Tabel Ongkos Kirim #

Contoh berikut membekukan Dictionary dan array menjadi dua koleksi frozen:

csharp
using System.Collections.Frozen;

Dictionary<string, int> ongkosSementara = new Dictionary<string, int>
{
    ["Bandung"] = 9000,
    ["Semarang"] = 14000,
    ["Medan"] = 18000
};

FrozenDictionary<string, int> ongkos = ongkosSementara.ToFrozenDictionary();
FrozenSet<string> kotaTerdaftar = new[] { "Bandung", "Semarang", "Medan" }.ToFrozenSet();

Console.WriteLine($"Ongkir Semarang: {ongkos["Semarang"]}");
Console.WriteLine($"Semarang terdaftar: {kotaTerdaftar.Contains("Semarang")}");
Console.WriteLine($"Makassar terdaftar: {kotaTerdaftar.Contains("Makassar")}");
Console.WriteLine($"Jumlah kota: {kotaTerdaftar.Count}");

Output yang Dihasilkan:

text
Ongkir Semarang: 14000
Semarang terdaftar: True
Makassar terdaftar: False
Jumlah kota: 3

Mari kita bedah baris demi baris:

  1. ongkosSementara: data disusun dulu sebagai Dictionary<TKey, TValue> biasa, karena penyusunan paling nyaman dilakukan pada tipe yang bisa diubah.
  2. ongkosSementara.ToFrozenDictionary(): momen pembekuan; runtime menganalisis tiga kunci dan menetapkan struktur internal yang tidak akan berubah lagi.
  3. new[] { ... }.ToFrozenSet(): array nama kota menjadi FrozenSet<T>; urutan asli tidak dijanjikan, yang dijanjikan adalah keanggotaan.
  4. ongkos["Semarang"]: pembacaan lewat indexer terasa sama seperti Dictionary<TKey, TValue>, hanya saja lebih cepat pada kumpulan kunci yang besar.
  5. kotaTerdaftar.Contains("Makassar"): pengecekan keanggotaan mengembalikan False tanpa memindai item satu per satu, karena posisi kandidat sudah dihitung saat pembekuan.

Bab berikutnya menyentuh keluarga koleksi terakhir sebelum kita menutup dengan topik performa dan desain: koleksi yang justru dirancang untuk ditulis oleh banyak pihak secara bersamaan.