Bab Iterator Pattern menunjukkan bahwa membuat iterator manual membutuhkan class terpisah, field posisi, dan tiga member. Untuk method yang menghasilkan urutan data, beban itu bisa dilepas ke compiler. Kata kunci yield return mengubah sebuah method biasa menjadi iterator method: method yang mengirim item satu per satu, dan compiler yang menulis class state machine di belakang layar.

Aturan Iterator Method #

Sebuah method menjadi iterator method bila memenuhi tiga syarat:

  • Return type-nya IEnumerable<T>, IEnumerator<T>, atau versi non-generiknya.
  • Badan method mengandung minimal satu yield return atau yield break.
  • Pernyataan yield return tidak boleh berada di dalam blok try yang memiliki klausa catch; compiler menolaknya dengan galat CS1626.

Bila syarat terpenuhi, compiler membangun class rahasia yang mengimplementasikan IEnumerable<T> dan IEnumerator<T> sekaligus, lengkap dengan field posisi dan pelacakan status. Tidak ada class tambahan yang perlu kita tulis.

Contoh: Menyusun Menu Vegetarian #

Method berikut mengirim dua item langsung, lalu melanjutkan dengan isi array lewat loop:

csharp
public static IEnumerable<string> MenuVegetarian()
{
    yield return "Gado-gado";
    yield return "Sayur Asem";

    string[] menuTambahan = { "Tumis Kangkung", "Pecel Sayur" };
    foreach (string makanan in menuTambahan)
    {
        yield return makanan;
    }
}

foreach (string makanan in MenuVegetarian())
{
    Console.WriteLine(makanan);
}

Output yang Dihasilkan:

text
Gado-gado
Sayur Asem
Tumis Kangkung
Pecel Sayur

Mari kita bedah baris demi baris:

  1. public static IEnumerable<string> MenuVegetarian(): return type adalah urutan item, bukan List<string>; method tidak mengumpulkan isi, tetapi menjanjikan urutan.
  2. yield return "Gado-gado";: item pertama dikirim, lalu eksekusi method menjeda persis di baris ini sampai konsumen meminta item berikutnya.
  3. yield return "Sayur Asem";: setelah konsumen meminta lagi, eksekusi dilanjutkan dari titik jeda; item kedua dikirim dan method menjeda lagi.
  4. foreach ... yield return makanan;: loop di dalam iterator method sah dan berguna; setiap putaran mengirim satu item dari menuTambahan.
  5. foreach (string makanan in MenuVegetarian()): konsumen menerima enumerator hasil kerja compiler; MoveNext() pada konsumen memicu badan method berjalan sampai yield return berikutnya.

Dengan yield return, urutan data ditulis seperti daftar langkah biasa. Pertanyaan berikutnya: bagaimana menghentikan urutan sebelum semua item dikirim? Jawabannya adalah yield break pada bab berikutnya.