Ketika Anda harus mengulang pembaca di mana jumlah item untuk dibaca tidak diketahui, dan satu-satunya cara untuk melakukannya adalah terus membaca sampai Anda mencapai akhir.
Ini adalah tempat yang sering Anda butuhkan perulangan tanpa akhir.
Selalu ada
true
yang menunjukkan harus adabreak
ataureturn
pernyataan di suatu tempat di dalam blok.int offset = 0; while(true) { Record r = Read(offset); if(r == null) { break; } // do work offset++; }
Ada pembacaan ganda untuk metode loop.
Record r = Read(0); for(int offset = 0; r != null; offset++) { r = Read(offset); if(r != null) { // do work } }
Ada loop baca sementara tunggal. Tidak semua bahasa mendukung metode ini .
int offset = 0; Record r = null; while((r = Read(++offset)) != null) { // do work }
Saya bertanya-tanya pendekatan mana yang paling tidak mungkin untuk memperkenalkan bug, yang paling mudah dibaca dan umum digunakan.
Setiap kali saya harus menulis salah satu dari ini saya pikir "harus ada cara yang lebih baik" .
c#
code-quality
readability
Reactgular
sumber
sumber
Jawaban:
Saya akan mengambil langkah kembali ke sini. Anda berkonsentrasi pada detail pilih-pilih kode tetapi melewatkan gambar yang lebih besar. Mari kita lihat salah satu contoh loop Anda:
Apa arti dari kode ini? Artinya adalah "lakukan beberapa pekerjaan untuk setiap catatan dalam file". Tapi bukan itu yang terlihat seperti kode . Kode tersebut terlihat seperti "mempertahankan offset. Buka file. Masukkan loop tanpa kondisi akhir. Baca catatan. Uji untuk nullity." Semua itu sebelum kita mulai bekerja! Pertanyaan yang harus Anda tanyakan adalah " bagaimana saya bisa membuat penampilan kode ini cocok dengan semantiknya? " Kode ini harus:
Sekarang kode itu dibaca seperti niatnya. Pisahkan mekanisme Anda dari semantik Anda . Dalam kode asli Anda, Anda mencampur mekanisme - rincian loop - dengan semantik - pekerjaan yang dilakukan untuk setiap catatan.
Sekarang kita harus mengimplementasikan
RecordsFromFile()
. Apa cara terbaik untuk mengimplementasikannya? Siapa peduli? Itu bukan kode yang akan dilihat siapa pun. Ini kode mekanisme dasar dan panjangnya sepuluh baris. Tulis sesuai keinginan Anda. Bagaimana dengan ini?Sekarang kita sedang memanipulasi urutan catatan dengan malas yang dihitung, segala macam skenario menjadi mungkin:
Dan seterusnya.
Setiap kali Anda menulis sebuah loop, tanyakan pada diri Anda "apakah loop ini membaca seperti mekanisme atau seperti arti dari kode?" Jika jawabannya "seperti mekanisme", maka cobalah untuk memindahkan mekanisme itu ke metode sendiri, dan tulis kode untuk membuat maknanya lebih terlihat.
sumber
Anda tidak perlu loop tanpa akhir. Anda seharusnya tidak memerlukan satu skenario C # baca. Ini adalah pendekatan yang saya sukai, dengan asumsi bahwa Anda benar-benar perlu mempertahankan offset:
Pendekatan ini mengakui fakta bahwa ada langkah pengaturan untuk pembaca, jadi ada dua panggilan metode baca. The
while
syarat adalah di bagian atas loop, hanya dalam kasus tidak ada data sama sekali dalam pembaca.sumber
Baik itu tergantung pada situasi Anda. Tapi salah satu solusi "C # -ish" yang dapat saya pikirkan adalah menggunakan antarmuka IEnumerable bawaan dan loop foreach. Antarmuka untuk IEnumerator hanya memanggil MoveNext dengan benar atau salah, sehingga ukurannya tidak diketahui. Kemudian logika terminasi Anda ditulis sekali - di enumerator - dan Anda tidak perlu mengulangi lebih dari satu tempat.
MSDN memberikan contoh IEnumerator <T> . Anda juga perlu membuat IEnumerable <T> untuk mengembalikan IEnumerator <T>.
sumber
Ketika saya memiliki operasi inisialisasi, kondisi dan kenaikan, saya suka menggunakan for for loop bahasa seperti C, C ++ dan C #. Seperti ini:
Atau ini jika Anda pikir ini lebih mudah dibaca. Saya pribadi lebih suka yang pertama.
sumber