Daftar <T> atau IList <T> [ditutup]

495

Adakah yang bisa menjelaskan kepada saya mengapa saya ingin menggunakan IList over List di C #?

Pertanyaan terkait: Mengapa dianggap buruk untuk diungkapkanList<T>

Kacang
sumber
1
pencarian internet untuk "kode ke antarmuka bukan implementasi" dan Anda dapat membaca sepanjang hari..dan menemukan beberapa perang.
granadaCoder

Jawaban:

446

Jika Anda mengekspos kelas Anda melalui perpustakaan yang akan digunakan orang lain, Anda biasanya ingin mengeksposnya melalui antarmuka daripada implementasi konkret. Ini akan membantu jika Anda memutuskan untuk mengubah implementasi kelas Anda nanti untuk menggunakan kelas konkret yang berbeda. Dalam hal ini pengguna perpustakaan Anda tidak perlu memperbarui kode mereka karena antarmuka tidak berubah.

Jika Anda hanya menggunakannya secara internal, Anda mungkin tidak terlalu peduli, dan menggunakan List<T>mungkin tidak masalah.

tvanfosson
sumber
19
Saya tidak mengerti perbedaan (halus), apakah ada beberapa contoh yang bisa Anda tunjukkan?
StingyJack
134
Katakanlah Anda awalnya menggunakan Daftar <T> dan ingin mengubah untuk menggunakan CaseInsensitiveList <T> khusus, yang keduanya mengimplementasikan IList <T>. Jika Anda menggunakan tipe konkret, semua penelepon perlu diperbarui. Jika diekspos sebagai IList <T> pemanggil tidak perlu diubah.
tvanfosson
46
Ah. BAIK. Saya mengerti. Memilih penyebut umum terendah untuk suatu kontrak. Terima kasih!
StingyJack
16
Prinsip ini adalah contoh enkapsulasi, salah satu dari tiga pilar pemrograman berorientasi objek. Idenya adalah Anda menyembunyikan detail implementasi dari pengguna, dan sebaliknya menyediakannya dengan antarmuka yang stabil. Ini untuk mengurangi ketergantungan pada detail yang mungkin berubah di masa depan.
jason
14
Perhatikan juga bahwa T []: IList <T>, sehingga untuk alasan kinerja Anda selalu dapat bertukar dari mengembalikan Daftar <T> dari prosedur Anda ke mengembalikan T [], dan jika prosedur tersebut dinyatakan untuk mengembalikan IList <T> (atau mungkin ICollection <T>, atau IEnumerable <T>) tidak ada lagi yang perlu diubah.
yfeldblum
322

Jawaban yang kurang populer adalah programmer suka berpura-pura perangkat lunak mereka akan digunakan kembali di seluruh dunia, ketika infact mayoritas proyek akan dikelola oleh sejumlah kecil orang dan betapapun bagusnya soundbite yang berhubungan dengan antarmuka, Anda menipu dirimu sendiri.

Astronot Arsitektur . Kemungkinan Anda akan pernah menulis IList Anda sendiri yang menambahkan apa pun ke yang sudah ada di .NET framework sangat jauh sehingga secara teoritis jeli tots disediakan untuk "praktik terbaik".

Astronot perangkat lunak

Tentunya jika Anda ditanya mana yang Anda gunakan dalam sebuah wawancara, Anda mengatakan IList, tersenyum, dan keduanya terlihat senang pada diri sendiri karena begitu pintar. Atau untuk API yang menghadap publik, IList. Semoga Anda mengerti maksud saya.

Arec Barrwin
sumber
65
Saya harus tidak setuju dengan jawaban sinis Anda. Saya tidak sepenuhnya tidak setuju dengan sentimen over-arsitektur yang menjadi masalah nyata. Namun saya pikir itu terutama dalam hal koleksi yang antarmuka benar-benar bersinar. Katakanlah saya memiliki fungsi yang mengembalikan IEnumerable<string>, di dalam fungsi tersebut saya dapat menggunakan a List<string>untuk toko dukungan internal untuk menghasilkan koleksi saya, tetapi saya hanya ingin penelepon untuk menyebutkan isinya, bukan menambah atau menghapus. Menerima antarmuka sebagai parameter mengkomunikasikan pesan yang sama "Saya butuh koleksi string, jangan khawatir, saya tidak akan mengubahnya."
Joshperry
38
Pengembangan perangkat lunak adalah semua tentang maksud menerjemahkan. Jika Anda berpikir bahwa antarmuka hanya berguna untuk membangun arsitektur yang terlalu besar dan megah dan tidak memiliki tempat di toko-toko kecil, maka saya berharap orang yang duduk di hadapan Anda dalam wawancara bukan saya.
Joshperry
48
Seseorang harus mengatakan ini Arec ... bahkan jika Anda punya segala macam pola akademik mengejar surat kebencian sebagai hasilnya. Memberi +1 kepada kita semua yang membencinya ketika aplikasi kecil dimuat dengan antarmuka dan mengeklik "temukan definisi" membawa kita ke tempat yang LAIN daripada sumber masalahnya ... Bisakah saya meminjam frasa "Astronot Arsitektur"? Aku bisa melihatnya akan berguna.
Gats
6
Jika mungkin, saya akan memberi Anda 1000 poin untuk jawaban ini. : D
Samuel
8
Saya berbicara tentang hasil pengejaran pola yang lebih luas. Antarmuka untuk antarmuka umum baik, lapisan ekstra demi mengejar pola, buruk.
Gats
186

Antarmuka adalah janji (atau kontrak).

Seperti selalu dengan janji-janji - semakin kecil semakin baik .

Rinat Abdullin
sumber
56
Tidak selalu lebih baik, lebih mudah disimpan! :)
Kirk Broadhurst
5
Saya tidak mengerti. Begitu IListjuga janjinya. Manakah janji yang lebih kecil dan lebih baik di sini? Ini tidak masuk akal.
nawfal
3
Untuk kelas lain saya setuju. Tetapi tidak untuk List<T>, karena AddRangetidak didefinisikan pada antarmuka.
Jesse de Wit
3
Ini tidak terlalu membantu dalam kasus khusus ini. Janji terbaik adalah yang ditepati. IList<T>membuat janji yang tidak bisa ditepati. Misalnya, ada Addmetode yang bisa melempar jika IList<T>kebetulan hanya baca. List<T>di sisi lain selalu dapat ditulis dan dengan demikian selalu menepati janjinya. Juga, sejak .NET 4.6, kami sekarang memiliki IReadOnlyCollection<T>dan IReadOnlyList<T>yang hampir selalu lebih cocok daripada IList<T>. Dan mereka kovarian. Hindari IList<T>!
ZunTzu
@ ZunTzu Saya berpendapat bahwa seseorang yang melepaskan koleksi abadi sebagai yang bisa berubah-ubah telah dengan sengaja melanggar kontrak yang disajikan - itu bukan masalah dengan kontrak itu sendiri, misalnya IList<T>. Seseorang bisa saja menerapkan IReadOnlyList<T>dan membuat setiap metode melemparkan pengecualian juga. Ini semacam kebalikan dari mengetik bebek - Anda menyebutnya bebek, tapi tidak bisa seperti dukun. Itu adalah bagian dari kontrak, meskipun kompiler tidak dapat menegakkannya. Saya setuju 100% IReadOnlyList<T>atau IReadOnlyCollection<T>harus digunakan untuk akses baca saja.
Shelby Oldfield
93

Beberapa orang mengatakan "selalu gunakan IList<T>bukan List<T>".
Mereka ingin Anda mengubah tanda tangan metode Anda dari void Foo(List<T> input)menjadi void Foo(IList<T> input).

Orang-orang ini salah.

Lebih bernuansa dari itu. Jika Anda mengembalikan IList<T>sebagai bagian dari antarmuka publik ke perpustakaan Anda, Anda meninggalkan sendiri opsi menarik untuk membuat daftar kustom di masa depan. Anda mungkin tidak pernah membutuhkan opsi itu, tetapi ini adalah argumen. Saya pikir itu adalah seluruh argumen untuk mengembalikan antarmuka bukan tipe konkret. Perlu disebutkan, tetapi dalam kasus ini memiliki kelemahan yang serius.

Sebagai counterargument kecil, Anda mungkin menemukan bahwa setiap penelepon membutuhkan List<T>, dan kode panggilan dipenuhi.ToList()

Tetapi jauh lebih penting, jika Anda menerima IList sebagai parameter Anda sebaiknya berhati-hati, karena IList<T>dan List<T>tidak berperilaku seperti itu. Terlepas dari kesamaan nama, dan meskipun berbagi antarmuka, mereka tidak mengekspos kontrak yang sama .

Misalkan Anda memiliki metode ini:

public Foo(List<int> a)
{
    a.Add(someNumber);
}

Seorang kolega yang membantu "refactor" metode untuk menerima IList<int>.

Kode Anda sekarang rusak, karena int[]mengimplementasikan IList<int>, tetapi ukurannya tetap. Kontrak untuk ICollection<T>(pangkalan IList<T>) memerlukan kode yang menggunakannya untuk memeriksa IsReadOnlybendera sebelum mencoba menambah atau menghapus item dari koleksi. Kontrak untuk List<T>tidak.

Prinsip Pergantian Liskov (disederhanakan) menyatakan bahwa tipe turunan harus dapat digunakan sebagai pengganti tipe dasar, tanpa prasyarat atau postkondisi tambahan.

Ini terasa seperti melanggar prinsip substitusi Liskov.

 int[] array = new[] {1, 2, 3};
 IList<int> ilist = array;

 ilist.Add(4); // throws System.NotSupportedException
 ilist.Insert(0, 0); // throws System.NotSupportedException
 ilist.Remove(3); // throws System.NotSupportedException
 ilist.RemoveAt(0); // throws System.NotSupportedException

Tapi ternyata tidak. Jawabannya adalah bahwa contoh yang digunakan IList <T> / ICollection <T> salah. Jika Anda menggunakan ICollection <T> Anda perlu memeriksa flag IsReadOnly.

if (!ilist.IsReadOnly)
{
   ilist.Add(4);
   ilist.Insert(0, 0); 
   ilist.Remove(3);
   ilist.RemoveAt(0);
}
else
{
   // what were you planning to do if you were given a read only list anyway?
}

Jika seseorang melewati Anda Array atau Daftar, kode Anda akan berfungsi dengan baik jika Anda memeriksa bendera setiap kali dan memiliki mundur ... Tapi sungguh; siapa yang melakukan itu? Apakah Anda tidak tahu sebelumnya jika metode Anda membutuhkan daftar yang dapat mengambil anggota tambahan; tidakkah Anda menyebutkannya dalam tanda tangan metode? Apa sebenarnya yang akan Anda lakukan jika Anda lulus daftar hanya baca seperti int[]?

Anda dapat mengganti List<T>menjadi kode yang menggunakan IList<T>/ ICollection<T> dengan benar . Anda tidak dapat menjamin bahwa Anda dapat mengganti kode ke IList<T>/ ICollection<T>yang menggunakan List<T>.

Ada seruan untuk Prinsip Tanggung Jawab Tunggal / Prinsip Pemisahan Antarmuka dalam banyak argumen untuk menggunakan abstraksi dan bukan tipe konkret - bergantung pada antarmuka sesempit mungkin. Dalam kebanyakan kasus, jika Anda menggunakan List<T>dan Anda pikir Anda bisa menggunakan antarmuka yang lebih sempit - mengapa tidak IEnumerable<T>? Ini seringkali lebih cocok jika Anda tidak perlu menambahkan item. Jika Anda perlu menambah koleksi, gunakan jenis beton List<T>,.

Bagi saya IList<T>(dan ICollection<T>) adalah bagian terburuk dari kerangka .NET. IsReadOnlymelanggar prinsip paling tidak mengejutkan. Kelas, seperti Array, yang tidak pernah mengizinkan penambahan, penyisipan atau penghapusan item tidak boleh mengimplementasikan antarmuka dengan metode Tambah, Sisipkan dan Hapus. (lihat juga /software/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties )

Apakah IList<T>cocok untuk organisasi Anda? Jika seorang rekan meminta Anda untuk mengubah metode tanda tangan untuk menggunakan IList<T>bukan List<T>, meminta mereka bagaimana mereka akan menambahkan elemen ke IList<T>. Jika mereka tidak tahuIsReadOnly (dan kebanyakan orang tidak), maka jangan gunakan IList<T>. Pernah.


Perhatikan bahwa flag IsReadOnly berasal dari ICollection <T>, dan menunjukkan apakah item dapat ditambahkan atau dihapus dari koleksi; tetapi hanya untuk benar-benar membingungkan hal-hal, itu tidak menunjukkan apakah mereka dapat diganti, yang dalam kasus Array (yang mengembalikan IsReadOnlys == true) bisa.

Untuk lebih lanjut tentang IsReadOnly, lihat definisi msdn dari ICollection <T> .IsReadOnly

perfeksionis
sumber
5
Hebat, jawaban bagus. Saya ingin menambahkan bahwa, bahkan jika IsReadOnlyadalah trueuntuk IList, Anda masih dapat memodifikasi anggota saat ini! Mungkin properti itu harus dinamai IsFixedSize?
xofz
(yang diuji dengan lulus Arraysebagai IList, jadi itu sebabnya saya bisa memodifikasi anggota saat ini)
xofz
1
@SamPearson ada properti IsFixedSize pada IList di .NET 1, tidak termasuk dalam IList generik .NET 2.0 <T> di mana ia dikonsolidasikan dengan IsReadOnly, yang mengarah ke perilaku mengejutkan di sekitar Array. Ada blog yang mencairkan otak yang terperinci tentang perbedaan-perbedaan halus di sini: enterprisecraftsmanship.com/2014/11/22/…
perfeksionis
7
Jawaban yang sangat bagus! Juga, sejak .NET 4.6, kami sekarang memiliki IReadOnlyCollection<T>dan IReadOnlyList<T>yang hampir selalu lebih cocok daripada IList<T>tetapi tidak memiliki semantik malas berbahaya IEnumerable<T>. Dan mereka kovarian. Hindari IList<T>!
ZunTzu
37

List<T>adalah implementasi spesifik IList<T>, yang merupakan wadah yang dapat dialamatkan dengan cara yang sama seperti array linier T[]menggunakan indeks integer. Ketika Anda menentukan IList<T>sebagai jenis argumen metode, Anda hanya menentukan bahwa Anda memerlukan kemampuan tertentu dari wadah.

Misalnya, spesifikasi antarmuka tidak memberlakukan struktur data tertentu untuk digunakan. Implementasi List<T>terjadi pada kinerja yang sama untuk mengakses, menghapus, dan menambahkan elemen sebagai array linier. Namun, Anda dapat membayangkan implementasi yang didukung oleh daftar tertaut, yang menambahkan elemen pada akhirnya lebih murah (waktu konstan) tetapi akses acak jauh lebih mahal. (Perhatikan bahwa NET LinkedList<T>tidak tidak melaksanakan IList<T>.)

Contoh ini juga memberi tahu Anda bahwa mungkin ada situasi ketika Anda perlu menentukan implementasinya, bukan antarmuka, dalam daftar argumen: Dalam contoh ini, setiap kali Anda memerlukan karakteristik kinerja akses tertentu. Ini biasanya dijamin untuk implementasi wadah tertentu ( List<T>dokumentasi: "Ini mengimplementasikan IList<T>antarmuka generik menggunakan array yang ukurannya secara dinamis ditingkatkan sesuai kebutuhan.").

Selain itu, Anda mungkin ingin mempertimbangkan untuk mengekspos fungsionalitas yang paling Anda butuhkan. Sebagai contoh. jika Anda tidak perlu mengubah konten daftar, Anda mungkin harus mempertimbangkan untuk menggunakan IEnumerable<T>, yang IList<T>meluas.

ILoveFortran
sumber
Mengenai pernyataan terakhir Anda tentang menggunakan IEnumerable, bukan IList. Ini tidak selalu disarankan, ambil WPF misalnya yang hanya akan membuat objek pembungkus IList sehingga akan memiliki dampak perf - msdn.microsoft.com/en-us/library/bb613546.aspx
HAdes
1
Jawaban yang bagus, jaminan kinerja adalah sesuatu yang tidak bisa dihasilkan oleh antarmuka. Dalam beberapa kode ini bisa sangat penting dan menggunakan kelas konkret mengkomunikasikan maksud Anda, kebutuhan Anda untuk kelas tertentu. Antarmuka di sisi lain mengatakan "Saya hanya perlu memanggil set metode ini, tidak ada kontrak lain yang tersirat."
Joshperry
1
@ joshperry Jika kinerja antarmuka mengganggu Anda, Anda berada di platform yang salah. Impo, ini adalah optimasi mikro.
nawfal
@nawfal Saya tidak mengomentari pro / kontra kinerja antarmuka. Saya menyetujui dan mengomentari fakta bahwa ketika Anda memilih untuk mengekspos kelas konkret sebagai argumen, Anda dapat mengomunikasikan maksud kinerja. Mengambil LinkedList<T>vs mengambil List<T>vs IList<T>semua mengkomunikasikan sesuatu dari jaminan kinerja yang diperlukan oleh kode yang dipanggil.
joshperry
28

Saya akan membalikkan sedikit pertanyaan, alih-alih membenarkan mengapa Anda harus menggunakan antarmuka dibandingkan implementasi konkret, cobalah untuk membenarkan mengapa Anda akan menggunakan implementasi konkret daripada antarmuka. Jika Anda tidak dapat membenarkannya, gunakan antarmuka.

Patrik Hägne
sumber
1
Cara berpikir yang sangat menarik tentang hal itu. Dan cara yang baik untuk berpikir saat pemrograman - terima kasih.
Kacang
Dikatakan dengan baik! Karena antarmuka adalah pendekatan yang lebih fleksibel, Anda benar-benar harus membenarkan apa implementasi konkret membeli Anda.
Cory House
9
Cara berpikir yang bagus. Masih saya bisa menjawabnya: alasan saya disebut AddRange ()
PPC
4
alasan saya disebut Add (). terkadang Anda ingin daftar yang Anda tahu dapat mengambil elemen tambahan, tentunya? Lihat jawaban saya.
perfeksionis
19

IList <T> adalah antarmuka sehingga Anda dapat mewarisi kelas lain dan masih menerapkan IList <T> saat mewarisi Daftar <T> mencegah Anda untuk melakukannya.

Misalnya jika ada kelas A dan kelas B Anda mewarisinya maka Anda tidak dapat menggunakan Daftar <T>

class A : B, IList<T> { ... }
Diadistis
sumber
15

Prinsip TDD dan OOP umumnya adalah pemrograman ke antarmuka bukan implementasi.

Dalam kasus khusus ini karena Anda pada dasarnya berbicara tentang konstruksi bahasa, bukan kebiasaan yang umumnya tidak masalah, tetapi katakan misalnya bahwa Anda menemukan Daftar tidak mendukung sesuatu yang Anda butuhkan. Jika Anda telah menggunakan IList di sisa aplikasi, Anda dapat memperluas Daftar dengan kelas khusus Anda sendiri dan masih dapat meneruskannya tanpa refactoring.

Biaya untuk melakukan ini sangat minim, mengapa tidak menyelamatkan diri dari sakit kepala nanti? Ini adalah prinsip antarmuka.

annakata
sumber
3
Jika ExtendedList <T> Anda mewarisi Daftar <T>, maka Anda masih dapat memasukkannya dalam kontrak <T> Daftar. Argumen ini hanya berfungsi jika Anda menulis implementasi IList <T> Anda sendiri dari awal (atau setidaknya tanpa mewarisi Daftar <T>)
PPC
14
public void Foo(IList<Bar> list)
{
     // Do Something with the list here.
}

Dalam hal ini Anda bisa lulus di kelas mana saja yang mengimplementasikan antarmuka <istar> IList. Jika Anda menggunakan Daftar <Bar> sebagai gantinya, hanya instance Daftar <Bar> yang dapat diteruskan.

Cara <Bar> IList lebih longgar daripada cara <Bar> Daftar.

smack0007
sumber
13

Mengejutkan bahwa tidak satu pun dari daftar ini vs. pertanyaan IList (atau jawaban) yang menyebutkan perbedaan tanda tangan. (Itulah sebabnya saya mencari pertanyaan ini di SO!)

Jadi, inilah metode yang terdapat dalam Daftar yang tidak ditemukan di IList, setidaknya pada .NET 4.5 (sekitar 2015)

  • AddRange
  • AsReadOnly
  • BinarySearch
  • Kapasitas
  • Konversi Semua
  • Ada
  • Temukan
  • Temukan semua
  • TemukanIndex
  • Temukan Terakhir
  • TemukanLastIndex
  • Untuk setiap
  • GetRange
  • InsertRange
  • LastIndexOf
  • Menghapus semua
  • RemoveRange
  • Balik
  • Menyortir
  • ToArray
  • TrimExcess
  • TrueForAll
JasonS
sumber
1
Tidak sepenuhnya benar. Reversedan ToArraymerupakan metode ekstensi untuk antarmuka <n> IEnumerable, yang berasal dari <isti> IList.
Tarec
Itu karena ini hanya masuk akal Listdan bukan implementasi lainnya IList.
HankCa
12

Kasus paling penting untuk menggunakan antarmuka atas implementasi adalah pada parameter untuk API Anda. Jika API Anda mengambil parameter Daftar, maka siapa pun yang menggunakannya harus menggunakan Daftar. Jika tipe parameternya adalah IList, maka pemanggil memiliki lebih banyak kebebasan, dan dapat menggunakan kelas yang tidak pernah Anda dengar, yang bahkan mungkin tidak ada ketika kode Anda ditulis.

Michael Borgwardt
sumber
7

Bagaimana jika NET 5.0 Menggantikan System.Collections.Generic.List<T>ke System.Collection.Generics.LinearList<T>. .NET selalu memiliki nama List<T>tetapi mereka menjamin ituIList<T> adalah kontrak. Jadi IMHO kita (minimal I) tidak seharusnya menggunakan nama seseorang (meskipun. NET dalam hal ini) dan mendapat masalah nanti.

Dalam hal menggunakan IList<T>, penelepon selalu dijamin hal-hal untuk bekerja, dan pelaksana bebas untuk mengubah koleksi yang mendasarinya untuk setiap implementasi konkret alternatif.IList

Soundararajan
sumber
7

Semua konsep pada dasarnya dinyatakan dalam sebagian besar jawaban di atas mengenai mengapa menggunakan antarmuka dibandingkan implementasi konkret.

IList<T> defines those methods (not including extension methods)

IList<T> Tautan MSDN

  1. Menambahkan
  2. Bersih
  3. Mengandung
  4. Salin ke
  5. GetEnumerator
  6. Indeks
  7. Memasukkan
  8. Menghapus
  9. RemoveAt

List<T> mengimplementasikan sembilan metode tersebut (tidak termasuk metode ekstensi), selain itu ia memiliki sekitar 41 metode publik, yang mempertimbangkan Anda mana yang akan digunakan dalam aplikasi Anda.

List<T> Tautan MSDN

yantaq
sumber
4

Anda akan karena mendefinisikan IList atau ICollection akan terbuka untuk implementasi lain dari antarmuka Anda.

Anda mungkin ingin memiliki IOrderRepository yang mendefinisikan kumpulan pesanan baik dalam IList atau ICollection. Anda kemudian dapat memiliki berbagai jenis implementasi untuk memberikan daftar pesanan selama itu sesuai dengan "aturan" yang ditentukan oleh IList atau ICollection Anda.

Peter Lindholm
sumber
3

IList <> hampir selalu lebih disukai sesuai saran poster lain, namun perhatikan ada bug di .NET 3.5 sp 1 saat menjalankan IList <> melalui lebih dari satu siklus serialisasi / deserialisasi dengan WCF DataContractSerializer.

Sekarang ada SP untuk memperbaiki bug ini: KB 971030

StuartLC
sumber
2

Antarmuka memastikan bahwa Anda setidaknya mendapatkan metode yang Anda harapkan ; menyadari definisi yaitu antarmuka. semua metode abstrak yang ada diimplementasikan oleh kelas apa pun yang mewarisi antarmuka. jadi jika seseorang membuat kelas besar sendiri dengan beberapa metode selain yang ia warisi dari antarmuka untuk beberapa fungsi tambahan, dan itu tidak berguna bagi Anda, lebih baik menggunakan referensi ke subkelas (dalam hal ini antarmuka) dan menetapkan objek kelas konkret untuk itu.

keuntungan tambahan adalah bahwa kode Anda aman dari perubahan apa pun pada kelas beton karena Anda hanya berlangganan sedikit metode kelas beton dan itulah yang akan ada di sana selama kelas beton mewarisi dari antarmuka Anda. menggunakan. jadi keamanannya bagi Anda dan kebebasan bagi pembuat kode yang menulis implementasi konkret untuk mengubah atau menambahkan lebih banyak fungsi ke kelas konkretnya.

vishy
sumber
2

Anda dapat melihat argumen ini dari beberapa sudut termasuk salah satu dari pendekatan OO murni yang mengatakan untuk memprogram terhadap Antarmuka bukan implementasi. Dengan pemikiran ini, menggunakan IList mengikuti prinsipal yang sama seperti berkeliling dan menggunakan Antarmuka yang Anda tetapkan dari awal. Saya juga percaya pada skalabilitas dan faktor fleksibilitas yang disediakan oleh Interface secara umum. Jika kelas mengimplementasikan IList <T> perlu diperluas atau diubah, kode yang digunakan tidak harus berubah; ia tahu apa yang dipatuhi kontrak Antarmuka IList. Namun menggunakan implementasi konkret dan Daftar <T> pada kelas yang berubah, dapat menyebabkan kode panggilan juga perlu diubah. Ini karena kelas yang mematuhi IList <T> menjamin perilaku tertentu yang tidak dijamin oleh tipe konkret menggunakan Daftar <T>.

Juga memiliki kekuatan untuk melakukan sesuatu seperti memodifikasi implementasi standar Daftar <T> pada kelas Menerapkan IList <T> untuk mengatakan .Add, .Remove atau metode IList lainnya memberi pengembang banyak fleksibilitas dan kekuatan, jika tidak ditentukan sebelumnya berdasarkan Daftar <T>

atconway
sumber
0

Biasanya, pendekatan yang baik adalah dengan menggunakan IList di API Anda yang menghadap publik (bila perlu, dan cantumkan semantik), dan kemudian Daftarkan secara internal untuk mengimplementasikan API. Ini memungkinkan Anda untuk mengubah ke implementasi IList yang berbeda tanpa melanggar kode yang menggunakan kelas Anda.

Daftar nama kelas dapat diubah dalam kerangka kerja .net berikutnya tetapi antarmuka tidak akan pernah berubah karena antarmuka kontrak.

Perhatikan bahwa, jika API Anda hanya akan digunakan dalam loop foreach, dll, maka Anda mungkin ingin mempertimbangkan hanya mengekspos IEnumerable saja.

lazydeveloper
sumber