Saya telah melihat beberapa programmer menggunakan ini:
foreach (var item in items)
{
if (item.Field != null)
continue;
if (item.State != ItemStates.Deleted)
continue;
// code
}
alih-alih di tempat yang biasanya saya gunakan:
foreach (var item in items.Where(i => i.Field != null && i.State != ItemStates.Deleted))
{
// code
}
Saya bahkan telah melihat kombinasi keduanya. Saya sangat suka keterbacaan dengan 'terus', terutama dengan kondisi yang lebih kompleks. Apakah ada perbedaan kinerja? Dengan permintaan basis data, saya berasumsi akan ada. Bagaimana dengan daftar reguler?
c#
readability
loops
filtering
Paprik
sumber
sumber
Jawaban:
Saya akan menganggap ini sebagai tempat yang tepat untuk menggunakan pemisahan perintah / permintaan . Sebagai contoh:
Ini juga memungkinkan Anda untuk memberikan nama yang mendokumentasikan diri sendiri dengan baik ke hasil kueri. Ini juga membantu Anda melihat peluang untuk refactoring, karena jauh lebih mudah untuk melakukan refactor kode yang hanya menanyakan data atau hanya mengubah data daripada kode campuran yang mencoba melakukan keduanya.
Saat men-debug, Anda dapat memutuskan sebelum
foreach
dengan cepat memeriksa apakah isi darivalidItems
penyelesaian sesuai dengan yang Anda harapkan. Anda tidak harus masuk ke lambda kecuali Anda perlu. Jika Anda perlu masuk ke dalam lambda, maka saya sarankan untuk memfaktorkannya ke dalam fungsi yang terpisah, kemudian melangkah melalui itu.Apakah ada perbedaan kinerja? Jika kueri didukung oleh database, maka versi LINQ memiliki potensi untuk berjalan lebih cepat, karena kueri SQL mungkin lebih efisien. Jika itu LINQ untuk Objek, maka Anda tidak akan melihat perbedaan kinerja nyata. Seperti biasa, buat profil kode Anda dan perbaiki kemacetan yang sebenarnya dilaporkan, alih-alih mencoba memprediksi optimisasi sebelumnya.
sumber
IEnumerable
sedang didorong olehforeach
loop saja.Where
lambda dan loop body (jika lambda mengembalikan true) sekali per elemen.Tentu saja ada perbedaan dalam kinerja,
.Where()
menghasilkan panggilan delegasi yang dibuat untuk setiap item. Namun, saya tidak akan khawatir sama sekali tentang kinerja:Siklus jam yang digunakan dalam memanggil delegasi dapat diabaikan dibandingkan dengan siklus jam yang digunakan oleh sisa kode yang diputar selama pengumpulan dan memeriksa kondisi.
Hukuman kinerja untuk memanggil seorang delegasi adalah urutan beberapa siklus clock, dan untungnya, kita sudah melewati hari-hari ketika kita harus khawatir tentang siklus clock individual.
Jika karena alasan tertentu kinerja benar - benar penting bagi Anda pada tingkat siklus clock, maka gunakan
List<Item>
alih-alihIList<Item>
, sehingga kompiler dapat menggunakan panggilan langsung (dan tidak dapat ditelepon) alih-alih panggilan virtual, dan agar iteratorList<T>
, yang sebenarnya astruct
, tidak harus kotak. Tapi itu hal-hal sepele.Permintaan basis data adalah situasi yang berbeda, karena ada (setidaknya secara teori) kemungkinan mengirim filter ke RDBMS, sehingga sangat meningkatkan kinerja: hanya baris yang cocok yang akan melakukan perjalanan dari RDBMS ke program Anda. Tetapi untuk itu saya pikir Anda harus menggunakan LINQ, saya tidak berpikir ungkapan ini bisa dikirim ke RDBMS seperti apa adanya.
Anda akan benar-benar melihat manfaat dari
if(x) continue;
saat Anda harus men-debug kode ini: Single-stepping overif()
andcontinue
s berfungsi dengan baik; satu langkah ke dalam delegasi penyaringan adalah rasa sakit.sumber
if(x) continue;
..Where
hanya dipanggil sekali. Apa yang dipanggil pada setiap iterasi adalah delegasi filter (MoveNext
danCurrent
pada enumerator, ketika mereka tidak dioptimalkan).Where
hanya dipanggil sekali. Memperbaikinya.