Saat saya menulis DAL saya atau kode lain yang mengembalikan sekumpulan item, haruskah saya selalu membuat pernyataan pengembalian:
public IEnumerable<FooBar> GetRecentItems()
atau
public IList<FooBar> GetRecentItems()
Saat ini, dalam kode saya, saya telah mencoba menggunakan IEnumerable sebanyak mungkin tetapi saya tidak yakin apakah ini adalah praktik terbaik? Sepertinya benar karena saya mengembalikan tipe data paling umum sambil tetap mendeskripsikan apa yang dilakukannya, tetapi mungkin ini tidak benar untuk dilakukan.
c#
ienumerable
KingNestor
sumber
sumber
Jawaban:
Itu benar-benar tergantung pada mengapa Anda menggunakan antarmuka khusus itu.
Misalnya,
IList<T>
memiliki beberapa metode yang tidak ada diIEnumerable<T>
:IndexOf(T item)
Insert(int index, T item)
RemoveAt(int index)
dan Properti:
T this[int index] { get; set; }
Jika Anda membutuhkan metode ini dengan cara apa pun, silakan kembali
IList<T>
.Selain itu, jika metode yang menggunakanIEnumerable<T>
hasil Anda mengharapkanIList<T>
, itu akan menghemat CLR dari mempertimbangkan setiap konversi yang diperlukan, sehingga mengoptimalkan kode yang dikompilasi.sumber
Panduan desain kerangka merekomendasikan penggunaan class Collection saat Anda perlu mengembalikan koleksi yang dapat dimodifikasi oleh pemanggil atau ReadOnlyCollection untuk koleksi hanya baca.
Alasan ini lebih disukai daripada yang sederhana
IList
adalah karenaIList
tidak memberi tahu penelepon apakah itu hanya baca atau tidak.Jika Anda mengembalikan
IEnumerable<T>
, operasi tertentu mungkin sedikit lebih rumit untuk dilakukan oleh pemanggil. Anda juga tidak akan lagi memberi penelepon fleksibilitas untuk mengubah koleksinya, sesuatu yang mungkin Anda inginkan atau tidak inginkan.Perlu diingat bahwa LINQ berisi beberapa trik dan akan mengoptimalkan panggilan tertentu berdasarkan jenisnya. Jadi, misalnya, jika Anda menjalankan a
Count
dan koleksi yang mendasarinya adalah List, ini TIDAK akan berjalan melalui semua elemen.Secara pribadi, untuk ORM saya mungkin akan tetap menggunakannya
Collection<T>
sebagai nilai pengembalian saya.sumber
Secara umum, Anda harus meminta yang paling umum dan mengembalikan hal paling spesifik yang Anda bisa. Jadi jika Anda memiliki metode yang mengambil parameter, dan Anda hanya benar-benar membutuhkan apa yang tersedia di IEnumerable, maka itu harus menjadi jenis parameter Anda. Jika metode Anda dapat menampilkan IList atau IEnumerable, lebih baik menampilkan IList. Ini memastikan bahwa ini dapat digunakan oleh konsumen yang paling luas.
Bebaskan apa yang Anda butuhkan, dan jelaskan apa yang Anda berikan.
sumber
Itu tergantung...
Mengembalikan type yang paling sedikit diturunkan (
IEnumerable
) akan memberi Anda kelonggaran paling besar untuk mengubah implementasi yang mendasari di jalurnya.Mengembalikan type yang lebih diturunkan (
IList
) memberi pengguna API Anda lebih banyak operasi pada hasilnya.Saya selalu menyarankan untuk mengembalikan jenis yang paling tidak diturunkan yang memiliki semua operasi yang dibutuhkan pengguna Anda ... jadi pada dasarnya, Anda harus terlebih dahulu membatalkan operasi apa pada hasil yang masuk akal dalam konteks API yang Anda tentukan.
sumber
Satu hal yang perlu dipertimbangkan adalah jika Anda menggunakan pernyataan LINQ eksekusi-ditangguhkan untuk menghasilkan Anda
IEnumerable<T>
, memanggil.ToList()
sebelum Anda kembali dari metode Anda berarti bahwa item Anda mungkin diulang dua kali - sekali untuk membuat Daftar, dan sekali ketika pemanggil mengulang melalui , memfilter, atau mengubah nilai pengembalian Anda. Ketika praktis, saya suka menghindari mengubah hasil LINQ-to-Objects menjadi Daftar atau Kamus konkret sampai saya harus melakukannya. Jika pemanggil saya membutuhkan List, itu adalah satu metode yang mudah untuk ditelepon - saya tidak perlu membuat keputusan itu untuk mereka, dan itu membuat kode saya sedikit lebih efisien dalam kasus di mana pemanggil hanya melakukan foreach.sumber
List<T>
menawarkan kode panggilan lebih banyak fitur, seperti memodifikasi objek yang dikembalikan dan akses dengan indeks. Jadi, pertanyaannya bermuara pada: dalam kasus penggunaan khusus aplikasi Anda, apakah Anda INGIN mendukung penggunaan tersebut (mungkin dengan mengembalikan koleksi yang baru dibuat!), Untuk kenyamanan pemanggil - atau apakah Anda menginginkan kecepatan untuk kasus sederhana ketika semua kebutuhan pemanggil adalah untuk mengulang melalui koleksi dan Anda dapat dengan aman mengembalikan referensi ke koleksi nyata yang mendasarinya tanpa takut ini akan membuatnya salah diubah, dll?Hanya Anda yang dapat menjawab pertanyaan ini, dan hanya dengan memahami dengan baik apa yang ingin dilakukan penelepon Anda dengan nilai pengembalian, dan seberapa penting kinerja di sini (seberapa besar koleksi yang akan Anda salin, seberapa besar kemungkinan ini menjadi hambatan, dll).
sumber
Jika koleksi dimaksudkan untuk menjadi hanya-baca, atau modifikasi koleksi dikendalikan oleh
Parent
pengembalian yangIList
adilCount
bukanlah ide yang baik.Di Linq, ada
Count()
metode ekstensiIEnumerable<T>
yang di dalam CLR akan pintas ke.Count
jika jenis yang mendasarinya adalahIList
, sehingga perbedaan kinerja dapat diabaikan.Secara umum saya merasa (pendapat) adalah praktik yang lebih baik untuk mengembalikan IEnumerable jika memungkinkan, jika Anda perlu melakukan penambahan maka tambahkan metode ini ke kelas induk, jika tidak, konsumen kemudian mengelola koleksi dalam Model yang melanggar prinsip, misalnya
manufacturer.Models.Add(model)
melanggar hukum demeter. Tentu saja ini hanyalah pedoman dan bukan aturan yang keras dan cepat, tetapi sampai Anda benar-benar memahami penerapannya, mengikuti secara membabi buta lebih baik daripada tidak mengikuti sama sekali.(Catatan: Jika menggunakan nNHibernate, Anda mungkin perlu memetakan ke IList pribadi menggunakan pengakses berbeda.)
sumber
Tidak sesederhana itu ketika Anda berbicara tentang nilai kembalian alih-alih parameter input. Jika itu adalah parameter masukan, Anda tahu persis apa yang perlu Anda lakukan. Jadi, jika Anda perlu untuk dapat mengulang koleksi, Anda mengambil IEnumberable sedangkan jika Anda perlu menambah atau menghapus, Anda menggunakan IList.
Dalam kasus nilai kembali, itu lebih sulit. Apa yang diharapkan penelepon Anda? Jika Anda mengembalikan IEnumerable, maka dia tidak akan tahu secara apriori bahwa dia dapat membuat IList darinya. Namun, jika Anda mengembalikan IList, dia akan tahu bahwa dia dapat mengulanginya. Jadi, Anda harus memperhitungkan apa yang akan dilakukan penelepon Anda dengan datanya. Fungsionalitas yang dibutuhkan / diharapkan pemanggil Anda adalah apa yang harus mengatur saat membuat keputusan tentang apa yang akan dikembalikan.
sumber
karena semua telah mengatakan itu tergantung, jika Anda tidak ingin Tambah / Hapus fungsi pada lapisan panggilan maka saya akan memilih IEnumerable karena hanya menyediakan iterasi dan fungsionalitas dasar yang dalam perspektif desain saya suka. Kembali ke IList, pilihan saya selalu lagi, tetapi itu terutama apa yang Anda suka dan apa yang tidak. dalam hal kinerja saya pikir mereka lebih mirip.
sumber
Jika Anda tidak menghitung dalam kode eksternal Anda, selalu lebih baik untuk mengembalikan IEnumerable, karena nanti Anda dapat mengubah implementasi Anda (tanpa dampak kode eksternal), misalnya, untuk logika iterator hasil dan menghemat sumber daya memori (fitur bahasa yang sangat baik dengan cara ).
Namun jika Anda membutuhkan item count, jangan lupa bahwa ada layer lain antara IEnumerable dan IList - ICollection .
sumber
Saya mungkin sedikit kesal di sini, melihat bahwa sejauh ini tidak ada orang lain yang menyarankannya, tetapi mengapa Anda tidak mengembalikannya
(I)Collection<T>
?Dari apa yang saya ingat,
Collection<T>
adalah tipe pengembalian yang lebih disukaiList<T>
karena itu mengabstraksikan implementasinya. Mereka semua menerapkanIEnumerable
, tetapi bagi saya itu terdengar terlalu rendah untuk pekerjaan itu.sumber
Saya pikir Anda dapat menggunakan keduanya, tetapi masing-masing memiliki kegunaan. Pada dasarnya
List
adalahIEnumerable
tetapi Anda memiliki fungsionalitas hitungan, Tambahkan elemen, hapus elemenIEnumerable
tidak efisien untuk menghitung elemen, atau mendapatkan elemen tertentu dalam koleksi.List
adalah koleksi yang cocok untuk menemukan elemen tertentu, mudah untuk menambahkan elemen, atau menghapusnya.Umumnya saya mencoba menggunakan
List
jika memungkinkan karena ini memberi saya lebih banyak fleksibilitas.Gunakan
List<FooBar> getRecentItems()
daripadaIList<FooBar> GetRecentItems()
sumber
Saya pikir aturan umumnya adalah menggunakan kelas yang lebih spesifik untuk kembali, untuk menghindari melakukan pekerjaan yang tidak diperlukan dan memberikan lebih banyak opsi kepada pemanggil Anda.
Meskipun demikian, menurut saya lebih penting untuk mempertimbangkan kode di depan Anda yang sedang Anda tulis daripada kode yang akan ditulis oleh orang berikutnya (sesuai alasannya). Ini karena Anda dapat membuat asumsi tentang kode yang sudah ada.
Ingat bahwa memindahkan NAIK ke koleksi dari IEnumerable dalam sebuah antarmuka akan berfungsi, pindah ke IEnumerable dari koleksi akan merusak kode yang ada.
Jika semua pendapat ini tampak bertentangan, itu karena keputusannya subjektif.
sumber
TL; DR; - ringkasan
List
) untuk nilai yang dikembalikan dan jenis yang paling umum untuk parameter masukan bahkan dalam kasus pengumpulan.IReadOnlyList
atauIReadOnlyCollection
sebagai tipe nilai yang dikembalikan.Lebih
sumber