Saya telah melihat mereka digunakan dengan banyak cara yang sama, dan saya khawatir saya akan menempuh jalur dalam desain yang tidak dapat diubah jika saya tidak memahami ini dengan lebih baik. Juga, saya menggunakan .NET.
Saya telah melihat mereka digunakan dengan banyak cara yang sama, dan saya khawatir saya akan menempuh jalur dalam desain yang tidak dapat diubah jika saya tidak memahami ini dengan lebih baik. Juga, saya menggunakan .NET.
Jawaban:
Collection<T>
adalah pembungkus yang dapat disesuaikan IList<T>
. Meskipun IList<T>
tidak disegel, itu tidak memberikan poin kustomisasi apa pun. Collection<T>
Metode secara default didelegasikan ke IList<T>
metode standar , tetapi dapat dengan mudah diganti untuk melakukan apa yang Anda inginkan. Dimungkinkan juga untuk memasang acara di dalam Collection<T>
yang saya tidak percaya dapat dilakukan dengan IList.
Singkatnya, jauh lebih mudah untuk memperpanjangnya setelah terjadi, yang berpotensi berarti jauh lebih sedikit refactoring.
IList
, IList<T>
, List<T>
dll Singkatnya, Anda tidak tahu apakah itu akan disebut. Polimorfisme memperbaiki ini.
ObservableCollection<T>
sebagai contoh di mana metode diganti untuk memberi tahu tentang perubahan.
Di C #, ada tiga konsep untuk merepresentasikan sekantong benda. Untuk meningkatkan fitur, mereka adalah:
Enumerable tidak memiliki urutan. Anda tidak dapat menambah atau menghapus item dari set. Anda bahkan tidak bisa mendapatkan hitungan item di set. Ini secara ketat memungkinkan Anda mengakses setiap item dalam set, satu demi satu.
Koleksi adalah satu set yang dapat dimodifikasi. Anda dapat menambah dan menghapus objek dari himpunan, Anda juga bisa mendapatkan jumlah item dalam himpunan. Tetapi masih belum ada urutan, dan karena tidak ada urutan: tidak ada cara untuk mengakses item dengan indeks, juga tidak ada cara untuk mengurutkan.
Daftar adalah sekumpulan objek yang diurutkan. Anda dapat mengurutkan daftar, mengakses item berdasarkan indeks, menghapus item berdasarkan indeks.
Faktanya, ketika melihat antarmuka untuk ini, mereka membangun satu sama lain:
interface IEnumerable<T>
GetEnumeration<T>
interface ICollection<T> : IEnumerable<T>
Add
Remove
Clear
Count
interface IList<T> = ICollection<T>
Insert
IndexOf
RemoveAt
Saat mendeklarasikan variabel, atau parameter metode, Anda harus memilih untuk menggunakan
berdasarkan konseptual yang perlu Anda lakukan dengan himpunan objek.
Jika Anda hanya perlu melakukan sesuatu untuk setiap objek dalam daftar, Anda hanya perlu IEnumerable
:
void SaveEveryUser(IEnumerable<User> users)
{
for User u in users
...
}
Anda tidak peduli jika Pengguna disimpan dalam List<T>
, Collection<T>
, Array<T>
atau apa pun. Anda hanya membutuhkanIEnumerable<T>
antarmuka.
Jika Anda ingin dapat menambah, menghapus, atau menghitung item dalam satu set, gunakan Koleksi :
ICollection<User> users = new Collection<User>();
users.Add(new User());
Jika Anda peduli dengan tata urutan, dan ingin urutannya benar, gunakan Daftar :
IList<User> users = FetchUsers(db);
Dalam bentuk grafik:
| Feature | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| Enumerating items | X | X | X |
| | | | |
| Adding items | | X | X |
| Removing items | | X | X |
| Count of items | | X | X |
| | | | |
| Accessing by index | | | X |
| Removing by indexx | | | X |
| Getting index of item | | | X |
The List<T>
dan Collection<T>
in System.Collections.Generic
adalah dua kelas yang mengimplementasikan antarmuka ini; tetapi mereka bukan satu-satunya kelas:
ConcurrentBag<T>
adalah tas benda yang dipesan ( IEnumerable<T>
)LinkedList<T>
adalah tas di mana Anda tidak diizinkan untuk mengakses item menurut index ( ICollection
); tetapi Anda dapat menambahkan dan menghapus item dari koleksi secara sewenang-wenangSynchronizedCollection<T>
dalam koleksi terurut, di mana Anda dapat menambah / menghapus item berdasarkan indeksJadi, Anda dapat dengan mudah mengubah:
IEnumerable<User> users = new SynchronizedCollection<User>();
SaveEveryUser(users);
Pilih konsep yang Anda butuhkan, kemudian gunakan kelas yang sesuai.
ICollection<T>
dan IList<T>
. Implementasi konkret yang berbeda mungkin berperilaku berbeda. Misalnya jika Anda mengakses a List<T>
melalui IEnumerable<T>
antarmukanya, maka Anda tidak memiliki cara untuk menambah, menghapus, menyortir, atau menghitung item dalam daftar.
List<T>
ditujukan untuk penggunaan internal dalam kode aplikasi. Anda harus menghindari menulis API publik yang menerima atau mengembalikan List<T>
(pertimbangkan untuk menggunakan superclass atau antarmuka koleksi sebagai gantinya).
Collection<T>
menyajikan kelas dasar untuk koleksi khusus (meskipun dapat digunakan secara langsung).
Pertimbangkan untuk menggunakan Collection<T>
dalam kode Anda kecuali ada fitur khusus dariList<T>
yang Anda butuhkan.
Di atas hanyalah rekomendasi.
[Diadaptasi dari: Panduan Desain Kerangka, Edisi Kedua]
Dictionary<string, List<string>>
untuk mengembalikan List<string>
tidak apa-apa, karena status kamus hanya merangkum identitas daftar di dalamnya, bukan isinya.
List<T>
adalah wadah yang sangat umum dilihat, karena sangat serbaguna (dengan banyak metode praktis seperti Sort
,, Find
dll) - tetapi tidak memiliki titik ekstensi jika Anda ingin menimpa perilaku apa pun (centang item saat menyisipkan, misalnya).
Collection<T>
adalah pembungkus di sekitar IList<T>
(default ke List<T>
) - ia memiliki titik ekstensi ( virtual
metode), tetapi tidak banyak metode dukungan seperti Find
. Karena tipuan, ini sedikit lebih lambat dariList<T>
, tetapi tidak terlalu banyak.
Dengan LINQ, metode ekstra dalam List<T>
menjadi kurang penting, karena LINQ-to-Objek cenderung untuk memberikan mereka pula ... misalnya First(pred)
, OrderBy(...)
, dll
Daftar lebih cepat.
Lakukan misalnya
private void button1_Click(object sender, EventArgs e)
{
Collection<long> c = new Collection<long>();
Stopwatch s = new Stopwatch();
s.Start();
for (long i = 0; i <= 10000000; i++)
{
c.Add(i);
}
s.Stop();
MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString());
List<long> l = new List<long>();
Stopwatch s2 = new Stopwatch();
s2.Start();
for (long i = 0; i <= 10000000; i++)
{
l.Add(i);
}
s2.Stop();
MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString());
}
di mesin saya List<>
hampir dua kali lebih cepat.
Edit
Saya tidak mengerti mengapa orang-orang tidak menyukai ini. Baik di mesin kerja saya dan mesin rumah saya, kode Daftar <> 80% lebih cepat.
List merepresentasikan koleksi yang urutan itemnya penting. Ini juga mendukung metode Sortir dan pencarian. Koleksi adalah struktur data yang lebih umum yang membuat lebih sedikit asumsi tentang data dan juga mendukung lebih sedikit metode untuk memanipulasinya. Jika Anda ingin mengekspos struktur data kustom, Anda mungkin harus memperluas koleksi. Jika Anda perlu memanipulasi data tanpa mengekspos struktur data, daftar mungkin adalah cara yang lebih nyaman untuk digunakan.
Ini adalah salah satu pertanyaan sekolah pascasarjana. Koleksi T adalah semacam abstrak; mungkin ada implementasi default (saya bukan orang .net / c #) tetapi koleksi akan memiliki operasi dasar seperti menambah, menghapus, mengulang, dan sebagainya.
Daftar T menyiratkan beberapa hal spesifik tentang operasi ini: menambahkan harus mengambil waktu yang konstan, menghapus harus mengambil waktu sebanding dengan jumlah elemen, getfirst harus waktu yang sama. Secara umum, Daftar adalah sejenis Koleksi, tetapi Koleksi belum tentu merupakan jenis Daftar.
Hanselman Speaks : " Collection<T>
terlihat seperti daftar, dan bahkan memiliki List<T>
internal. SETIAP metode tunggal didelegasikan ke internal List<T>
. Ini termasuk properti terlindungi yang mengekspos List<T>
."
EDIT: Collection<T>
tidak ada di System.Generic.Collections .NET 3.5. Jika Anda bermigrasi dari .NET 2.0 ke 3.5 Anda perlu mengubah beberapa kode jika Anda menggunakan banyakCollection<T>
objek, kecuali saya kehilangan sesuatu yang jelas ...
EDIT 2: Collection<T>
sekarang dalam namespace System.Collections.ObjectModel di .NET 3.5. File bantuan mengatakan ini:
"Ruang nama System.Collections.ObjectModel berisi kelas yang dapat digunakan sebagai koleksi dalam model objek perpustakaan yang dapat digunakan kembali. Gunakan kelas ini saat properti atau metode mengembalikan koleksi."
Semua antarmuka ini diwarisi IEnumerable
, yang harus Anda pastikan Anda mengerti. Antarmuka itu pada dasarnya memungkinkan Anda menggunakan kelas dalam pernyataan foreach (dalam C #).
ICollection
adalah antarmuka paling dasar yang Anda daftarkan. Ini adalah antarmuka yang tak terhitung banyaknya yang mendukung Count
dan hanya itu.IList
adalah segalanya ICollection
, tetapi juga mendukung penambahan dan penghapusan item, mengambil item berdasarkan indeks, dll. Ini adalah antarmuka yang paling umum digunakan untuk "daftar objek", yang saya tahu tidak jelas.IQueryable
adalah antarmuka yang dapat dihitung yang mendukung LINQ. Anda selalu dapat membuat IQueryable
dari IList dan menggunakan LINQ ke Objek, tetapi Anda juga dapat menemukan IQueryable
digunakan untuk eksekusi pernyataan SQL yang ditangguhkan di LINQ ke SQL dan LINQ ke Entitas.IDictionary
adalah hewan yang berbeda dalam arti bahwa ini adalah pemetaan kunci unik untuk nilai. Ini juga dapat dihitung sehingga Anda dapat menghitung pasangan kunci / nilai, tetapi selain itu melayani tujuan yang berbeda dari yang lain yang Anda cantumkanMenurut MSDN, List (Of T) .Add adalah "operasi O (n)" (ketika "Kapasitas" terlampaui) sedangkan Collection (Of T) .Add selalu "operasi O (1)". Itu akan bisa dimengerti jika List diimplementasikan menggunakan Array dan Collection a Linked List. Namun, jika itu masalahnya, orang akan mengharapkan Collection (Of T) .Item menjadi "operasi O (n)". Tapi - ini - tidak !?! Collection (Of T) .Item adalah "operasi O (1)" seperti List (Of T) .Item.
Selain itu, "tuinstoel "'s" Dec 29 '08 at 22:31 "posting di atas mengklaim tes kecepatan menunjukkan Daftar (Dari T). Tambahkan menjadi lebih cepat daripada Koleksi (Dari T). Tambahkan yang telah saya reproduksi dengan Panjang dan String. Meskipun saya hanya mendapatkan ~ 33% lebih cepat vs. klaimnya 80%, menurut MSDN, seharusnya sebaliknya dan dengan "n" kali!?!
Keduanya menerapkan antarmuka yang sama, jadi mereka akan berperilaku dengan cara yang sama. Mungkin mereka diterapkan secara berbeda secara internal, tetapi ini harus diuji.
Satu-satunya perbedaan nyata yang saya lihat adalah ruang nama dan fakta yang Collection<T>
ditandai dengan ComVisibleAttribute(false)
, jadi kode COM tidak dapat menggunakannya.
Selain jawaban lain, saya telah menyusun ikhtisar singkat tentang daftar umum dan kemampuan pengumpulan. Koleksi adalah bagian terbatas dari Daftar:
* = sekarang
o = hadir sebagian
Pengumpulan Properti / Metode < T > Daftar < T > --------------------------------------- -------
Add() * *
AddRange() *
AsReadOnly() *
BinarySearch() *
Capacity *
Clear() * *
Contains() * *
ConvertAll() *
CopyTo() o *
Count * *
Equals() * *
Exists() *
Find() *
FindAll() *
FindIndex() *
FindLast() *
FindLastIndex() *
ForEach() *
GetEnumerator() * *
GetHashCode() * *
GetRange() *
GetType() * *
IndexOf() o *
Insert() * *
InsertRange() *
Item() * *
LastIndexOf() *
New() o *
ReferenceEquals() * *
Remove() * *
RemoveAll() *
RemoveAt() * *
RemoveRange() *
Reverse() *
Sort() *
ToArray() *
ToString() * *
TrimExcess() *
TrueForAll() *