Lihat definisi kelas System.Array
public abstract class Array : IList, ...
Secara teoritis, saya harus bisa menulis ini sedikit dan bahagia
int[] list = new int[] {};
IList iList = (IList)list;
Saya juga harus dapat memanggil metode apa pun dari iList
ilist.Add(1); //exception here
Pertanyaan saya bukan mengapa saya mendapatkan pengecualian, melainkan mengapa Array mengimplementasikan IList ?
c#
arrays
ilist
liskov-substitution-principle
oleksii
sumber
sumber
Jawaban:
Karena sebuah array memungkinkan akses cepat dengan indeks, dan
IList
/IList<T>
adalah satu-satunya antarmuka pengumpulan yang mendukung ini. Jadi mungkin pertanyaan Anda yang sebenarnya adalah "Mengapa tidak ada antarmuka untuk koleksi konstan dengan pengindeks?" Dan untuk itu saya tidak punya jawaban.Juga tidak ada antarmuka baca untuk koleksi. Dan saya kehilangan mereka bahkan lebih dari ukuran konstan dengan antarmuka pengindeks.
IMO harus ada beberapa antarmuka pengumpulan (generik) tergantung pada fitur koleksi. Dan nama-nama itu seharusnya juga berbeda,
List
karena sesuatu dengan pengindeks adalah IMO yang benar-benar bodoh.IEnumerable<T>
ICollection<T>
IList<T>
Saya pikir antarmuka koleksi saat ini adalah desain yang buruk. Tetapi karena mereka memiliki properti yang memberitahu Anda metode mana yang valid (dan ini adalah bagian dari kontrak metode ini) itu tidak melanggar prinsip substitusi.
sumber
add
dan karenanya tidak dapat digantikan dengan sesuatu yang berfungsi saat kemampuan itu diperlukan.IsFixedSize
danIsReadOnly
properti, itu pasti melanggar prinsip Tell, Don't Ask dan Prinsip yang paling tidak mengejutkan . Mengapa menerapkan antarmuka saat Anda hanya akan membuang pengecualian untuk 4 dari 9 metode?Bagian komentar dari dokumentasi untuk
IList
kataJelas array jatuh ke dalam kategori ukuran tetap, jadi oleh defisi antarmuka masuk akal.
sumber
Array
menerapkanAdd
metode secara eksplisit, yang mengurangi risiko memanggilnya secara tidak sengaja.IList
yang melarang modifikasi dan penambahan / penghapusan. Maka dokumentasi tidak lagi benar. : PKarena tidak semua
IList
s bisa berubah (lihatIList.IsFixedSize
danIList.IsReadOnly
), dan array tentu berperilaku seperti daftar ukuran tetap.Jika pertanyaan Anda benar-benar "mengapa ia mengimplementasikan antarmuka non-generik ", maka jawabannya adalah ini ada sebelum generik muncul.
sumber
IList
itu sendiri memberi tahu Anda bahwa itu mungkin tidak bisa berubah. Jika ternyata dijamin bisa berubah dan array mengatakan sebaliknya, maka itu akan melanggar aturan.IList<T>
dan tidak memecahnya dalam hal non-generikIList
: enterprisecraftsmanship.com/2014/11/22/...Ini adalah warisan yang kami miliki sejak saat tidak jelas bagaimana menangani koleksi hanya baca dan apakah Array hanya dibaca atau tidak. Ada bendera IsFixedSize dan IsReadOnly di antarmuka IList. Bendera IsReadOnly berarti bahwa koleksi tidak dapat diubah sama sekali dan IsFixedSize berarti bahwa koleksi memang memungkinkan modifikasi, tetapi tidak menambahkan atau menghapus item.
Pada saat .Net 4.5 jelas bahwa beberapa antarmuka "perantara" diperlukan untuk bekerja dengan koleksi hanya baca, jadi
IReadOnlyCollection<T>
danIReadOnlyList<T>
diperkenalkan.Berikut ini adalah posting blog hebat yang menjelaskan detail: Baca hanya koleksi di .NET
sumber
Definisi antarmuka IList adalah "Merupakan koleksi objek non-generik yang dapat diakses secara individual dengan indeks.". Array sepenuhnya memenuhi definisi ini, jadi harus mengimplementasikan antarmuka. Pengecualian saat memanggil metode Tambahkan () adalah "System.NotSupportedException: Koleksi berukuran tetap" dan terjadi karena array tidak dapat meningkatkan kapasitasnya secara dinamis. Kapasitasnya ditentukan selama pembuatan objek array.
sumber
Memiliki array yang mengimplementasikan IList (dan secara transitif, ICollection) menyederhanakan mesin Linq2Objects, karena casting IEnumerable ke IList / ICollection juga akan bekerja untuk array.
Sebagai contoh, Count () akhirnya memanggil Array. Panjang di bawah kap, karena itu dilemparkan ke ICollection dan implementasi array mengembalikan Panjang.
Tanpa ini, mesin Linq2Objects tidak akan memiliki perlakuan khusus untuk array dan berkinerja buruk, atau mereka perlu menggandakan kode menambahkan perlakuan kasus khusus untuk array (seperti yang mereka lakukan untuk IList). Mereka pasti memilih untuk membuat array mengimplementasikan IList saja.
Itu pendapat saya tentang "Kenapa".
sumber
Juga detail implementasi LINQ Pemeriksaan terakhir untuk IList, jika tidak menerapkan daftar, mereka akan membutuhkan 2 pemeriksaan memperlambat semua Panggilan terakhir atau memiliki Terakhir di Array mengambil O (N)
sumber