Dalam aplikasi web ASP.net MVC4 saya menggunakan IEnumerables, mencoba mengikuti mantra untuk memprogram ke antarmuka, bukan implementasi.
Return IEnumerable(Of Student)
vs.
Return New List(Of Student)
Orang-orang mengatakan kepada saya untuk menggunakan Daftar dan bukan IEnumerable, karena daftar memaksa kueri untuk dieksekusi dan IEumerable tidak.
Apakah ini benar-benar praktik terbaik? Apakah ada alternatif lain? Saya merasa aneh menggunakan benda konkret di mana antarmuka dapat digunakan. Apakah perasaan aneh saya dibenarkan?
.net
programming-practices
asp.net-mvc
entity-framework
Rowan Freeman
sumber
sumber
Jawaban:
Ada kalanya melakukan
ToList()
permintaan pada linq Anda bisa menjadi penting untuk memastikan permintaan Anda dieksekusi pada saat itu dan dalam urutan yang Anda harapkan. Namun skenario itu jarang terjadi dan tidak ada yang harus dikhawatirkan terlalu banyak sampai mereka benar-benar bertemu dengannya.Singkatnya, gunakan
IEnumerable
kapan saja Anda hanya perlu iterasi, gunakanIList
saat Anda perlu mengindeks secara langsung dan membutuhkan array berukuran dinamis (jika Anda perlu mengindeks pada array ukuran tetap maka gunakan saja array standar).Adapun hal waktu eksekusi, Anda selalu dapat menggunakan daftar sebagai
IEnumerable
variabel, jadi jangan ragu untuk mengembalikan sebuahIEnumerable
dengan melakukan.ToList();
, atau mengirimkan parameter sebagaiIEnumerable
dengan mengeksekusi.ToList()
padaIEnumerable
untuk memaksa eksekusi saat itu juga. Berhati-hatilah bahwa kapan saja Anda memaksa eksekusi dengan.ToList()
Anda, jangan bergantung padaIEnumerable
variabel yang baru saja Anda lakukan dan jalankan lagi, atau Anda akan berakhir dua kali lipat iterasi dalam permintaan LINQ Anda tidak perlu.Berkenaan dengan MVC, tidak ada yang istimewa untuk dicatat di sini. Ini akan mengikuti aturan waktu eksekusi yang sama dengan .NET, saya pikir Anda mungkin memiliki seseorang yang sedikit bingung oleh penundaan eksekusi semantik di masa lalu dan menyalahkannya pada MVC yang memberitahu Anda ini entah bagaimana terkait, tapi itu tidak. Semantik eksekusi yang tertunda membingungkan semua orang pada awalnya (dan bahkan untuk sementara waktu sesudahnya; mereka bisa menjadi sentuhan yang rumit). Sekali lagi, jangan khawatir tentang hal itu sampai Anda benar-benar peduli untuk memastikan permintaan LINQ tidak dieksekusi dua kali atau mengharuskannya dieksekusi dalam urutan tertentu relatif terhadap kode lain, di mana titik menetapkan variabel Anda untuk dirinya sendiri. Daftar () untuk memaksa eksekusi dan Anda akan baik-baik saja.
sumber
List
melewati sekitarList
menyiratkan bahwa isi daftar akan diubah. Jika Anda ingin mengembalikan koleksi, gunakanIReadOnlyCollection
.List
untuk digunakan di dalam metode, dan untuk pertukaran di antara metode yang mengubah daftar. Itu dia!Ada dua masalah.
Saat loop "Data Proses" tercapai, kueri mungkin tidak lagi valid. Misalnya, jika kueri dijalankan pada DataContext yang sudah dibuang, kode Anda akan mengeluarkan pengecualian. Hal semacam ini menjadi sangat membingungkan ketika Anda memproses kueri dalam konteks yang berbeda dari tempat Anda membuatnya.
Masalah kedua adalah bahwa koneksi Anda tidak akan dirilis sampai loop "Data Proses" selesai. Ini hanya masalah jika "Data Proses" kompleks. Ini disebutkan di http://msdn.microsoft.com/en-us/library/bb386929.aspx :
Jadi, masalah ini adalah alasan mengapa Anda didorong untuk memastikan bahwa kueri benar-benar dieksekusi, misalnya dengan menelepon
ToList()
. Namun, seperti yang disarankan oleh Jimmy, tidak ada yang menghentikan Anda mengembalikan Daftar sebagai IEnumerable.Sebagai aturan umum, saya sarankan menghindari iterasi lebih dari satu IEnumerable lebih dari sekali. Dengan asumsi konsumen kode Anda mengikuti aturan ini, saya tidak menganggapnya sebagai kekhawatiran bahwa seseorang mungkin menekan database dua kali dengan mengeksekusi kueri dua kali.
sumber
Manfaat lain dari penghitungan
IEnumerable
awal adalah pengecualian akan dilemparkan ke lokasi yang sesuai. Ini membantu debugging.Misalnya, jika Anda mendapatkan pengecualian kebuntuan di dalam salah satu tampilan Razor Anda, itu tidak akan benar-benar sejelas jika pengecualian terjadi selama salah satu metode akses data Anda.
sumber
IEnumerable
lemparan yang mungkin membuat kesalahan.IEnumerable
Metode yang ditangguhkan harus dibagi menjadi dua: satu metode yang tidak ditangguhkan memeriksa parameter dan mengatur, melempar jika perlu (katakanlah, karena argumen nol). Lalu ia mengembalikan panggilan untuk pelaksanaan swasta yang sedang ditangguhkan. Saya tidak berpikir komentar saya sepenuhnya bertentangan dengan jawaban Anda, tetapi jangan berpikir bahwa Anda telah meninggalkan aspek penting dalam jawaban Anda, yang merupakan makna semantik dari menggunakanIEnumerable
vs. aList
(mutasi) vsIReadOnlyCollection
(tidak ada manfaatnya untuk penangguhan) .