Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pilih iterator saat Anda ingin mengembalikan urutan yang elemennya dapat dikonsumsi pemanggil satu per satu, tanpa terlebih dahulu membangun hasil lengkap dalam koleksi. Pendekatan ini cocok untuk nilai yang dihasilkan, filter dengan alur kontrol kustom, dan urutan yang mungkin tidak dibaca sampai selesai oleh pemanggil. Dibandingkan dengan koleksi yang telah selesai, iterator mengubah kapan pekerjaan dilakukan, bukan hanya bagaimana Anda menulisnya.
Tip
Artikel ini mengajarkan iterator sinkron untuk pengembang yang mengetahui metode, perulangan, dan koleksi. Untuk sintaks dan batasan lengkap yield , lihat yield referensi pernyataan.
Metode iterator menghasilkan urutan nilai satu per satu. Artikel ini berfokus pada metode iterator yang mengembalikan IEnumerable<T>, yang nilainya biasanya digunakan oleh pemanggil dalam pernyataan foreach.
Menghasilkan elemen dengan yield return
Gunakan yield return untuk menyediakan elemen berikutnya dalam urutan. Iterator berikut memilih pembacaan suhu yang dapat diterima dari sensor. Dalam skenario ini, -1 menandai akhir data sensor.
int[] readings = [21, 27, 24, -1, 19];
IEnumerable<int> acceptedReadings =
SelectTemperatures(readings, maximum: 25);
Console.WriteLine("Sequence created.");
foreach (int temperature in acceptedReadings)
{
Console.WriteLine($"Accepted: {temperature}°C");
}
static IEnumerable<int> SelectTemperatures(
IEnumerable<int> readings,
int maximum)
{
foreach (int reading in readings)
{
Console.WriteLine($"Checking {reading}°C");
if (reading == -1)
{
yield break;
}
if (reading <= maximum)
{
yield return reading;
}
}
}
SelectTemperatures mengembalikan IEnumerable<int>, yang mewakili urutan nilai int. Masing-masing yield return reading memberikan satu nilai untuk perulangan foreach . Setelah pemanggil menangani nilai tersebut, iterator berlanjut dengan input berikutnya.
Gunakan bentuk generik IEnumerable<T> untuk sebagian besar kode C# modern. Argumen jenis, seperti int, memberi tahu pemanggil jenis elemen yang dikandung urutan.
Akhiri urutan dengan yield break
Gunakan yield break untuk mengakhiri iterator sebelum kontrol mencapai akhir metode. Dalam contoh, nilai -1 sentinel berarti bahwa tidak ada lagi pembacaan yang tersedia:
if (reading == -1)
{
yield break;
}
Iterator juga berakhir secara alami ketika eksekusi mencapai akhir isi bloknya. Gunakan yield break saat suatu kondisi seharusnya segera menghentikan produksi elemen.
Mengonsumsi iterator dengan foreach
Iterator mengekspos struktur yang sama IEnumerable<T> dengan banyak koleksi .NET. Pemanggil dapat menggunakan foreach tanpa mengetahui bagaimana urutan menghasilkan elemennya:
foreach (int temperature in SelectTemperatures(readings, 25))
{
Console.WriteLine($"Accepted: {temperature}°C");
}
Pemanggil meminta setiap elemen saat perulangan berjalan. Iterator mempertahankan posisinya di antara permintaan dan berlanjut setelah yield return sebelumnya.
Memahami pembuatan elemen tertunda
Memanggil metode iterator tidak segera menjalankan kode di dalamnya. Metode ini mulai menghasilkan elemen ketika pemanggil memulai enumerasi. Perilaku ini disebut eksekusi yang ditangguhkan.
Contoh ini mencetak Sequence created. sebelum pesan Checking ... apa pun. Iterator mulai memeriksa pembacaan hanya ketika perulangan foreach meminta elemen pertamanya.
Eksekusi yang ditangguhkan memiliki efek praktis:
- Pemanggil dapat mulai memproses sebelum iterator menghasilkan setiap elemen.
- Iterator dapat berhenti lebih awal dengan
yield break. - Pemanggil yang tidak pernah mengiterasi sekuens tidak menjalankan isi iterator.
- Setiap enumerasi baru menjalankan iterator lagi.
Perjelas eksekusi tertunda dalam tujuan dan dokumentasi metode. Pembaca tidak dapat menyimpulkan waktu eksekusi dari IEnumerable<T> sendirinya karena iterator dan koleksi dapat mengekspos antarmuka tersebut. Pastikan produksi elemen bebas dari efek samping yang tidak terkait karena pemanggil mungkin mengiterasi sekuens nanti atau lebih dari sekali. Pesan diagnostik pada contoh mengilustrasikan pengaturan waktu tersebut.
Pilih iterator atau koleksi
Mengembalikan iterator ketika nilai secara alami tiba satu per satu atau ketika pemanggil tidak segera memerlukan hasil lengkap. Mengembalikan koleksi lengkap saat penelepon memerlukan snapshot yang stabil, akses terindeks, atau enumerasi berulang tanpa menghitung ulang elemen.
Kedua pendekatan dapat mengembalikan elemen yang sama. Iterator menyerahkan produksi elemen di bawah kendali pemanggil; metode yang membangun koleksi menyelesaikan pekerjaan tersebut sebelum mengembalikan hasil.
Gunakan perulangan biasa saat Anda ingin melakukan tindakan untuk setiap item tanpa mengembalikan urutan. Untuk filter atau transformasi standar, lebih suka operasi LINQ seperti Where atau Select; tulis iterator saat logika elemen-produksi kustom lebih jelas sebagai serangkaian pernyataan.
Metode iterator dapat dikombinasikan dengan LINQ karena keduanya menggunakan IEnumerable<T>. Misalnya, penelepon dapat menambahkan filter lain:
var comfortableReadings = SelectTemperatures(readings, 25)
.Where(static temperature => temperature >= 18);
Operasi iterator dan LINQ tetap ditangguhkan sampai kode melakukan enumerasi pada comfortableReadings.
Untuk urutan asinkron, lihat Membuat dan mengonsumsi aliran asinkron. Untuk pola enumerasi kustom dan semua yield batasan, gunakan referensi bahasa.