Saya tahu bahwa IList adalah antarmuka dan Daftar adalah tipe konkret tapi saya masih tidak tahu kapan harus menggunakan masing-masing. Apa yang saya lakukan sekarang adalah jika saya tidak memerlukan metode Sort atau FindAll saya menggunakan antarmuka. Apakah saya benar? Apakah ada cara yang lebih baik untuk memutuskan kapan akan menggunakan antarmuka atau tipe konkret?
180
Jawaban:
Ada dua aturan yang saya ikuti:
Jadi ketika menulis fungsi atau metode yang mengambil koleksi, tulislah itu bukan untuk mengambil Daftar, tetapi sebuah IList <T>, sebuah ICollection <T>, atau IEnumerable <T>. Antarmuka generik masih akan bekerja bahkan untuk daftar heterogen karena System.Object bisa menjadi T juga. Melakukan hal ini akan menyelamatkan Anda dari sakit kepala jika Anda memutuskan untuk menggunakan Stack atau struktur data lain di ujung jalan. Jika semua yang perlu Anda lakukan dalam fungsi ini adalah untuk setiap langkah, IEnumerable <T> benar-benar yang harus Anda tanyakan.
Di sisi lain, saat mengembalikan objek dari suatu fungsi, Anda ingin memberi pengguna rangkaian operasi terkaya tanpa harus dilemparkan. Jadi dalam hal itu, jika itu Daftar <T> secara internal, kembalikan salinan sebagai Daftar <T>.
sumber
if...else
rantai denganis
kata kunci untuk mencari keluar tipe yang lebih kaya untuk itu dan akhirnya casting untuk itu dan menggunakannya pula. Jadi Anda tidak perlu dijamin menyembunyikan apa pun dengan menggunakan antarmuka dasar, bukan hanya mengaburkannya. Namun membuatnya lebih sulit juga dapat membuat penulis kode konsumsi berpikir dua kali tentang bagaimana mereka menggunakannya.Add()
danRemove()
mungkin memiliki efek di luar koleksi saja. Mengembalikan antarmuka hanya baca sepertiIEnumerable
sering kali merupakan cara untuk mencari metode pengambilan data. Konsumen Anda dapat memproyeksikannya menjadi tipe yang lebih kaya sesuai kebutuhan.Pedoman Microsoft sebagaimana dicentang oleh FxCop mencegah penggunaan Daftar <T> di API publik - lebih memilih IList <T>.
Kebetulan, saya sekarang hampir selalu mendeklarasikan array satu dimensi sebagai IList <T>, yang berarti saya dapat secara konsisten menggunakan properti IList <T> .Count daripada Array.Length. Sebagai contoh:
sumber
Ada hal penting yang selalu dilupakan orang:
Anda bisa meneruskan array sederhana ke sesuatu yang menerima
IList<T>
parameter, dan kemudian Anda bisa memanggilIList.Add()
dan akan menerima pengecualian runtime:Unhandled Exception: System.NotSupportedException: Collection was of a fixed size.
Misalnya, pertimbangkan kode berikut:
Jika Anda memanggilnya sebagai berikut, Anda akan mendapatkan pengecualian runtime:
Ini terjadi karena menggunakan array sederhana dengan
IList<T>
melanggar prinsip substitusi Liskov.Untuk alasan ini, jika Anda menelepon
IList<T>.Add()
Anda mungkin ingin mempertimbangkan untuk memintaList<T>
alih - alihIList<T>
.sumber
List<T>
lebih dipilihIList<T>
, Anda juga harus mengetahui alasan mengapaIList<T>
direkomendasikan. (Misalnya blogs.msdn.microsoft.com/kcwalina/2005/09/26/… )IList<T>.Add()
. Saya tidak mengatakan bahwa Anda tidak boleh menggunakanIList<T>
- Saya hanya menunjukkan kemungkinan jebakan. (Saya cenderung menggunakanIEnumerable<T>
atauIReadOnlyList<T>
atauIReadOnlyCollection<T>
lebih sukaIList<T>
jika saya bisa.)Saya setuju dengan saran Lee untuk mengambil parameter, tetapi tidak kembali.
Jika Anda menentukan metode Anda untuk mengembalikan antarmuka itu berarti Anda bebas untuk mengubah implementasi yang tepat di kemudian hari tanpa metode konsumsi yang pernah tahu. Saya pikir saya tidak perlu mengubah dari Daftar <T> tetapi kemudian harus mengubah untuk menggunakan pustaka daftar kustom untuk fungsionalitas tambahan yang disediakan. Karena saya hanya mengembalikan IList <T> tidak ada orang yang menggunakan perpustakaan harus mengubah kode mereka.
Tentu saja itu hanya perlu diterapkan pada metode yang terlihat secara eksternal (yaitu metode publik). Saya pribadi menggunakan antarmuka bahkan dalam kode internal, tetapi karena Anda dapat mengubah semua kode sendiri jika Anda membuat perubahan melanggar itu tidak sepenuhnya diperlukan.
sumber
IEnumerable
Anda harus mencoba dan menggunakan jenis paling tidak spesifik yang sesuai dengan tujuan Anda.
IEnumerable
kurang spesifik dariIList
.Anda gunakan
IEnumerable
saat Anda ingin mengulang item dalam koleksi.IList
Mengimplementasikan IListIEnumerable
.Anda harus menggunakannya
IList
saat Anda membutuhkan akses berdasarkan indeks ke koleksi Anda, menambah dan menghapus elemen, dll ...Daftar
List
alatIList
.sumber
Itu selalu terbaik untuk menggunakan jenis pangkalan serendah mungkin. Ini memberi pelaksana antarmuka Anda, atau konsumen metode Anda, kesempatan untuk menggunakan apa pun yang mereka suka di belakang layar.
Untuk koleksi, Anda harus berupaya menggunakan IEnumerable jika memungkinkan. Ini memberikan fleksibilitas paling tetapi tidak selalu cocok.
sumber
ToList()
mengembalikan AndaIEnumerable<T>
yang sudah menjadi daftar, danIList<T>
sebaliknya mengembalikan . Sekarang, klien dapat mengambil manfaat dari apa yang dapat Anda berikan tanpa usaha.Jika Anda bekerja dalam satu metode (atau bahkan dalam satu kelas atau perakitan dalam beberapa kasus) dan tidak ada orang luar yang akan melihat apa yang Anda lakukan, gunakan kepenuhan Daftar. Tetapi jika Anda berinteraksi dengan kode luar, seperti ketika Anda mengembalikan daftar dari suatu metode, maka Anda hanya ingin mendeklarasikan antarmuka tanpa harus mengikat diri Anda pada implementasi tertentu, terutama jika Anda tidak memiliki kontrol atas siapa yang mengkompilasi terhadap Anda kode sesudahnya. Jika Anda mulai dengan tipe konkret dan Anda memutuskan untuk beralih ke yang lain, meskipun itu menggunakan antarmuka yang sama, Anda akan merusak kode orang lain kecuali Anda memulai dengan antarmuka atau tipe basis abstrak.
sumber
Saya tidak berpikir ada aturan keras dan cepat untuk hal semacam ini, tapi saya biasanya mengikuti pedoman menggunakan cara yang paling ringan sampai benar-benar diperlukan.
Sebagai contoh, katakanlah Anda memiliki
Person
kelas danGroup
kelas. SebuahGroup
contoh memiliki banyak orang, sehingga Daftar di sini akan masuk akal. Ketika saya mendeklarasikan objek daftar diGroup
saya akan menggunakanIList<Person>
dan instantiate sebagaiList
.Dan, jika Anda bahkan tidak membutuhkan semua yang ada di dalamnya,
IList
Anda selalu dapat menggunakannyaIEnumerable
juga. Dengan kompiler dan prosesor modern, saya tidak berpikir ada perbedaan kecepatan sebenarnya, jadi ini hanya masalah gaya.sumber
Anda paling sering lebih baik menggunakan jenis yang paling umum digunakan, dalam hal ini IList atau bahkan lebih baik antarmuka IEnumerable, sehingga Anda dapat beralih implementasi dengan mudah di lain waktu.
Namun, dalam. NET 2.0, ada hal yang menjengkelkan - IList tidak memiliki metode Sort () . Anda dapat menggunakan adaptor yang disediakan sebagai gantinya:
sumber
Anda harus menggunakan antarmuka hanya jika Anda membutuhkannya, misalnya, jika daftar Anda dilemparkan ke implementasi IList selain Daftar. Ini benar ketika, misalnya, Anda menggunakan NHibernate, yang melemparkan ILists ke objek tas NHibernate saat mengambil data.
Jika Daftar adalah satu-satunya implementasi yang akan Anda gunakan untuk koleksi tertentu, silakan menyatakannya sebagai implementasi Daftar yang konkret.
sumber
Dalam situasi yang biasanya saya temui, saya jarang menggunakan IList secara langsung.
Biasanya saya hanya menggunakannya sebagai argumen untuk suatu metode
Ini akan memungkinkan saya untuk melakukan pemrosesan generik pada hampir semua array dalam kerangka NET., Kecuali menggunakan IEnumerable dan bukan IList, yang kadang-kadang terjadi.
Ini benar-benar turun ke jenis fungsi yang Anda butuhkan. Saya sarankan menggunakan kelas Daftar dalam banyak kasus. IList adalah yang terbaik untuk saat Anda perlu membuat larik kustom yang dapat memiliki beberapa aturan yang sangat spesifik yang ingin Anda enkapsulasi dalam koleksi sehingga Anda tidak mengulangi diri Anda sendiri, tetapi tetap ingin .NET mengenalinya sebagai daftar.
sumber
Objek AList memungkinkan Anda untuk membuat daftar, menambahkan sesuatu ke dalamnya, menghapusnya, memperbaruinya, mengindeks ke dalamnya dan lain-lain. Daftar digunakan kapan pun Anda hanya ingin Daftar generik tempat Anda menentukan jenis objek di dalamnya dan hanya itu.
IList di sisi lain adalah Interface. Pada dasarnya, jika Anda ingin membuat tipe Daftar Anda sendiri, ucapkan kelas daftar yang disebut BookList, maka Anda dapat menggunakan Antarmuka untuk memberi Anda metode dan struktur dasar untuk kelas baru Anda. IList adalah untuk saat Anda ingin membuat sendiri sub-kelas Anda yang mengimplementasikan Daftar.
Perbedaan lainnya adalah: IList adalah Antarmuka dan tidak dapat dipakai. Daftar adalah kelas dan bisa dipakai. Itu berarti:
sumber