Koleksi pada bab-bab sebelumnya adalah mutable: siapa pun yang memegang referensi bisa menambah, mengubah, atau menghapus isi kapan saja. Pada aplikasi besar, perubahan diam-diam dari bagian kode lain sering menjadi sumber bug yang sulit dilacak. Immutable collections menjawab masalah ini dengan aturan tegas: isi koleksi tidak pernah berubah, dan setiap operasi modifikasi mengembalikan koleksi baru, sementara koleksi lama tetap utuh.

Package System.Collections.Immutable #

Keluarga koleksi ini tinggal di namespace System.Collections.Immutable. Untuk target .NET Framework dan .NET Standard, tipe-tipe ini harus ditambahkan lewat NuGet:

bash
dotnet add package System.Collections.Immutable

Pada project verifikasi bab ini, perintah di atas menambahkan System.Collections.Immutable versi 10.0.13 yang diterbitkan oleh Microsoft. Bila aplikasi menargetkan .NET 9, tipe di dalamnya sudah termasuk bagian platform, sehingga kode berikut langsung terkompilasi tanpa package tambahan.

Modifikasi Tanpa Mengubah Asal #

Contoh berikut menambah item ke ImmutableArray<string> dan ImmutableDictionary<string, int>:

csharp
using System.Collections.Immutable;

ImmutableArray<string> menuDasar = ["Nasi Uduk", "Ketoprak"];
ImmutableArray<string> menuLengkap = menuDasar.Add("Sate Padang");

Console.WriteLine($"Menu dasar: {menuDasar.Length} item");
Console.WriteLine($"Menu lengkap: {menuLengkap.Length} item");
Console.WriteLine($"Menu dasar tetap: {string.Join(", ", menuDasar)}");

ImmutableDictionary<string, int> ongkosKirim =
    new Dictionary<string, int> { ["Bandung"] = 9000 }.ToImmutableDictionary();
ImmutableDictionary<string, int> ongkosBaru = ongkosKirim.Add("Medan", 18000);

Console.WriteLine($"Ongkir Medan (kamus baru): {ongkosBaru["Medan"]}");
Console.WriteLine($"Kamus lama memuat Medan: {ongkosKirim.ContainsKey("Medan")}");

Output yang Dihasilkan:

text
Menu dasar: 2 item
Menu lengkap: 3 item
Menu dasar tetap: Nasi Uduk, Ketoprak
Ongkir Medan (kamus baru): 18000
Kamus lama memuat Medan: False

Mari kita bedah baris demi baris:

  1. ImmutableArray<string> menuDasar = ["Nasi Uduk", "Ketoprak"];: collection expression yang diperkenalkan bab Collection Initialization juga berlaku untuk ImmutableArray<T>.
  2. menuDasar.Add("Sate Padang"): method Add tidak mengubah menuDasar; method mengembalikan array baru berisi tiga item, dan hasilnya disimpan di variabel berbeda.
  3. Menu dasar tetap: ...: baris ini membuktikan koleksi lama masih berisi dua item persis seperti sebelum Add dipanggil.
  4. .ToImmutableDictionary(): cara praktis mengubah Dictionary<TKey, TValue> biasa menjadi kamus immutable; perubahan berikutnya membuat versi baru, bukan menyentuh versi lama.
  5. Kamus lama memuat Medan: False: ongkosKirim dan ongkosBaru adalah dua objek terpisah; penambahan pada satu tidak merembet ke yang lain.

Immutable menjamin isi tidak berubah, tetapi tidak menjanjikan pencarian tercepat. Bab berikutnya memperkenalkan keluarga koleksi yang dioptimalkan khusus untuk dibaca setelah dibuat sekali.