Bagikan melalui


Ekstensi GetEnumerator dukungan untuk perulangan foreach.

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut tertuang dalam catatan catatan rapat desain bahasa (LDM) yang terkait.

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Masalah juara: https://github.com/dotnet/csharplang/issues/3194

Ringkasan

Izinkan perulangan foreach mengenali metode ekstensi GetEnumerator yang sebaliknya memenuhi pola foreach, dan mengulang ekspresi tersebut ketika sebaliknya akan menjadi kesalahan.

Motivasi

Ini akan membawa foreach selaras dengan cara fitur lain di C# diimplementasikan, termasuk asinkron dan dekonstruksi berbasis pola.

Desain terperinci

Perubahan spesifikasi relatif mudah. Kami memodifikasi bagian The foreach statement§13.9.5 ke teks ini:

Pemrosesan waktu kompilasi pernyataan foreach terlebih dahulu menentukan jenis koleksi , jenis enumerator dan jenis elemen ekspresi. Penentuan ini berlanjut sebagai berikut:

  • Jika jenis X ekspresi adalah jenis array, maka ada konversi referensi implisit dari X ke antarmuka IEnumerable (karena System.Array mengimplementasikan antarmuka ini). Jenis koleksi adalah antarmuka IEnumerable, jenis enumerator adalah antarmuka IEnumerator dan jenis elemen adalah jenis elemen dari jenis array X.

  • Jika jenis X dari ekspresi adalahdynamic, maka ada konversi implisit dari ekspresi ke antarmuka IEnumerable (§10.2.10). Jenis koleksi adalah antarmuka IEnumerable dan jenis enumerator adalah antarmuka IEnumerator. Jika pengidentifikasi var diberikan sebagai tipe_variabel_lokal maka jenis elemen adalah dynamic, jika tidak, itu adalah object.

  • Jika tidak, tentukan apakah jenis X memiliki metode GetEnumerator yang sesuai:

    • Lakukan pencarian anggota pada tipe X dengan pengidentifikasi GetEnumerator dan tidak ada argumen tipe. Jika pencarian anggota tidak menghasilkan kecocokan, atau menghasilkan ambiguitas, atau menghasilkan kecocokan yang bukan grup metode, periksa antarmuka yang dapat dihitung seperti yang dijelaskan di bawah ini. Disarankan agar peringatan dikeluarkan jika pencarian anggota menghasilkan apa pun kecuali grup metode atau tidak ada kecocokan.
    • Lakukan resolusi kelebihan beban menggunakan grup metode yang dihasilkan dan daftar argumen kosong. Jika resolusi kelebihan beban tidak menghasilkan metode yang berlaku, menghasilkan ambiguitas, atau menghasilkan satu metode terbaik tetapi metode itu statis atau bukan publik, periksa antarmuka yang dapat dihitung seperti yang dijelaskan di bawah ini. Disarankan agar peringatan dikeluarkan jika resolusi kelebihan beban menghasilkan apa pun kecuali metode instans publik yang tidak ambigu atau tidak ada metode yang berlaku.
    • Jika jenis pengembalian E metode GetEnumerator bukan kelas, struct atau jenis antarmuka, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Pencarian anggota dilakukan pada E dengan pengidentifikasi Current dan tidak ada argumen jenis. Jika pencarian anggota tidak menghasilkan kecocokan, hasilnya adalah kesalahan, atau hasilnya adalah apa pun kecuali properti instans publik yang mengizinkan pembacaan, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Pencarian anggota dilakukan pada E dengan pengidentifikasi MoveNext dan tidak ada argumen jenis. Jika pencarian anggota tidak menghasilkan kecocokan, hasilnya adalah kesalahan, atau hasilnya adalah apa pun kecuali grup metode, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Resolusi kelebihan beban dilakukan pada grup metode dengan daftar argumen kosong. Jika resolusi kelebihan beban tidak menghasilkan metode yang berlaku, menghasilkan ambiguitas, atau menghasilkan satu metode terbaik tetapi metode tersebut statis atau tidak publik, atau jenis pengembaliannya tidak bool, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Jenis koleksi X, jenis enumerator E, dan jenis elemen adalah jenis properti Current.
  • Jika tidak, periksa antarmuka yang dapat dijumlahkan:

    • Jika di antara semua jenis Ti yang ada konversi implisit dari X ke IEnumerable<Ti>, ada jenis unik T sehingga T tidak dynamic dan untuk semua Ti lainnya ada konversi implisit dari IEnumerable<T> ke IEnumerable<Ti>, maka jenis koleksi adalah antarmuka IEnumerable<T>, jenis enumerator adalah antarmuka IEnumerator<T>, dan jenis elemen T.
    • Jika tidak, jika ada lebih dari satu jenis tersebut T, maka muncul kesalahan dan tidak ada langkah lebih lanjut yang dilakukan.
    • Jika tidak, jika ada konversi implisit dari X ke antarmuka System.Collections.IEnumerable, maka jenis koleksi adalah antarmuka ini, jenis enumerator adalah antarmuka System.Collections.IEnumerator, dan jenis elemen object.
  • Jika tidak, tentukan apakah jenis 'X' memiliki metode ekstensi GetEnumerator yang sesuai:

    • Lakukan pencarian metode ekstensi pada jenis X dengan pengidentifikasi GetEnumerator. Jika pencarian anggota tidak menghasilkan kecocokan, atau menghasilkan ambiguitas, atau menghasilkan kecocokan yang bukan grup metode, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil. Disarankan agar peringatan diberikan jika pencarian anggota menghasilkan apa pun selain grup metode atau tidak ada kecocokan.
    • Lakukan resolusi kelebihan beban menggunakan grup metode yang dihasilkan dan satu argumen jenis X. Jika resolusi kelebihan beban tidak menghasilkan metode yang berlaku, menyebabkan ambiguitas, atau menghasilkan satu metode terbaik tetapi metode tersebut tidak dapat diakses, maka terjadi kesalahan dan tidak ada langkah lebih lanjut yang diambil.
      • Resolusi ini memungkinkan argumen pertama diberikan melalui ref jika X adalah jenis struct, dan jenis ref adalah in.
    • Jika jenis pengembalian E metode GetEnumerator bukan kelas, struct atau jenis antarmuka, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Pencarian anggota dilakukan pada E dengan pengidentifikasi Current dan tidak ada argumen jenis. Jika pencarian anggota tidak menghasilkan kecocokan, hasilnya adalah kesalahan, atau hasilnya adalah apa pun kecuali properti instans publik yang mengizinkan pembacaan, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Pencarian anggota dilakukan pada E dengan pengidentifikasi MoveNext dan tidak ada argumen jenis. Jika pencarian anggota tidak menghasilkan kecocokan, hasilnya adalah kesalahan, atau hasilnya adalah apa pun kecuali grup metode, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Resolusi kelebihan beban dilakukan pada grup metode dengan daftar argumen kosong. Jika resolusi kelebihan beban tidak menghasilkan metode yang berlaku, menghasilkan ambiguitas, atau menghasilkan satu metode terbaik tetapi metode tersebut statis atau tidak publik, atau jenis pengembaliannya tidak bool, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.
    • Jenis koleksi X, jenis enumerator E, dan jenis elemen adalah jenis properti Current.
  • Jika tidak, kesalahan dihasilkan dan tidak ada langkah lebih lanjut yang diambil.

Untuk await foreach, aturan juga dimodifikasi. Satu-satunya perubahan yang diperlukan pada spesifikasi tersebut adalah menghapus baris Extension methods do not contribute. dari deskripsi, karena spesifikasi lainnya didasarkan pada aturan di atas dengan nama yang berbeda yang digantikan untuk metode pola.

Kekurangan

Setiap perubahan menambah kompleksitas pada bahasa, dan ini berpotensi memungkinkan hal-hal yang awalnya tidak dirancang untuk di-foreach-kan menjadi di-foreach-kan, seperti Range.

Alternatif

Tidak melakukan apa-apa.

Pertanyaan yang belum terselesaikan

Tidak ada saat ini.