Bab Collection Initializers pada section Koleksi Dasar menunjukkan bahwa List<T> dan Dictionary<TKey, TValue> bisa diisi langsung saat deklarasi. Bab ini menyingkap dua hal yang belum dibahas di sana: syarat sebuah tipe agar initializer bisa dipakai, sehingga kita bisa membuat tipe koleksi sendiri yang mendukungnya, dan collection expression dari C# 12 yang menulis koleksi dengan kurung siku.

Syarat Mendukung Collection Initializer #

Compiler menerjemahkan isi initializer menjadi pemanggilan method Add. Agar bentuk new MenuWarung { ... } bisa dikompilasi, sebuah tipe perlu dua hal:

  • Mengimplementasikan IEnumerable, agar compiler tahu tipe tersebut memang sebuah koleksi.
  • Memiliki method bernama Add yang bisa dipanggil untuk setiap bentuk elemen di initializer.

Method Add boleh lebih dari satu; initializer akan memilih overload sesuai jumlah dan tipe argumen di setiap baris. Bentuk initializer klasik dan collection expression menghasilkan program dengan perilaku waktu berjalan yang sama; pembedanya ada pada kebebasan compiler, karena pada collection expression compiler boleh memilih strategi pembangunan yang lebih efisien.

Tipe Kustom dan Collection Expression #

Contoh berikut memakai dua overload Add sekaligus, lalu mencoba collection expression dengan spread element:

csharp
public class MenuWarung : IEnumerable<string>
{
    private readonly List<string> _menu = new List<string>();

    public void Add(string nama)
    {
        _menu.Add(nama);
    }

    public void Add(string nama, string kategori)
    {
        _menu.Add($"{kategori}: {nama}");
    }

    public IEnumerator<string> GetEnumerator()
    {
        return _menu.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

MenuWarung menuPagi = new MenuWarung
{
    "Nasi Uduk",
    { "Es Teh Manis", "Minuman" },
    "Kerak Telor"
};

int[] mejaLantaiSatu = { 1, 2, 3 };
List<int> semuaMeja = [.. mejaLantaiSatu, 4, 5];

foreach (string item in menuPagi)
{
    Console.WriteLine(item);
}
Console.WriteLine($"Nomor meja: {string.Join(", ", semuaMeja)}");

Output yang Dihasilkan:

text
Nasi Uduk
Minuman: Es Teh Manis
Kerak Telor
Nomor meja: 1, 2, 3, 4, 5

Mari kita bedah bagian pentingnya:

  1. "Nasi Uduk" dan "Kerak Telor": elemen tunggal diterjemahkan compiler menjadi pemanggilan Add(string), overload pertama.
  2. { "Es Teh Manis", "Minuman" }: pasangan dalam kurung kurawal dipetakan ke Add(string, string), overload kedua, sehingga kategori ikut tercatat.
  3. [.. mejaLantaiSatu, 4, 5]: collection expression C# 12 membuat List<int> baru; spread element .. menyalin seluruh isi array, lalu dua nilai tambahan disisipkan di akhir.
  4. string.Join(", ", semuaMeja): hasil akhir berisi lima nomor urut, membuktikan penyalinan spread mempertahankan urutan asli.

Dengan dua mekanisme ini, hampir semua tipe koleksi yang kita tulis bisa menerima data awal secara ringkas. Bab berikutnya mulai membahas keluarga koleksi yang tidak bisa diubah setelah dibuat: immutable collections.