Ini pertanyaan yang dekat, tapi saya pikir tidak persis sama. Ini menanyakan List<>secara umum, sementara yang itu bertanya List<object>secara spesifik
Ya, cukup banyak. List<T>adalah kelas generik. Ini mendukung menyimpan nilai-nilai dari jenis tertentu tanpa casting ke atau dari object(yang akan menyebabkan tinju / unboxing overhead ketika Tmerupakan tipe nilai dalam ArrayListcase). ArrayListhanya menyimpan objectreferensi. Sebagai kumpulan generik, List<T>mengimplementasikan IEnumerable<T>antarmuka generik dan dapat digunakan dengan mudah di LINQ (tanpa memerlukan apa pun Castatau OfTypepanggilan).
ArrayListmilik hari-hari dimana C # tidak memiliki obat generik. Sudah usang mendukung List<T>. Anda tidak boleh menggunakan ArrayListkode baru yang menargetkan .NET> = 2.0 kecuali Anda harus berinteraksi dengan API lama yang menggunakannya.
Maukah Anda menjelaskan mengapa Anda menggunakan "tinju" dan bukan "casting"? Tinju apa yang terjadi di sini? Apakah objek dialokasikan / tidak dialokasikan?
Benjamin Gruenbaum
2
@BenjaminGruenbaum Anda benar bahwa casting akan lebih umum. Yang mengatakan, perbedaan nyata saat runtime adalah ketika Anda berurusan dengan tipe nilai (yang saya anggap ketika saya menulis "tinju"). Untuk tipe referensi, perilaku secara efektif sama dengan ArrayListsaat runtime. Namun secara statis, itu akan membutuhkan para pemain ArrayList.
Mehrdad Afshari
Saya bertanya-tanya apakah kerangka kerja harus membatasi T menjadi tipe "objek", karena ArrayList secara implisit memungkinkan itu.
@ Ant_222, blog itu ditulis hampir 15 tahun yang lalu. Saya pikir bukti selama dekade terakhir telah menunjukkan bahwa obat generik tidak berbahaya. :)
Scott Adams
101
Menggunakan List<T>Anda dapat mencegah kesalahan casting. Sangat berguna untuk menghindari kesalahan casting runtime .
Contoh:
Di sini (menggunakan ArrayList) Anda dapat mengkompilasi kode ini tetapi Anda akan melihat kesalahan eksekusi nanti.
ArrayList array1 =newArrayList();
array1.Add(1);
array1.Add("Pony");//No error at compile processint total =0;foreach(int num in array1){
total += num;//-->Runtime Error}
Jika Anda menggunakan List, Anda menghindari kesalahan ini:
List<int> list1 =newList<int>();
list1.Add(1);//list1.Add("Pony"); //<-- Error at compile processint total =0;foreach(int num in list1 ){
total += num;}
Anda dapat memeriksa jenisnya saat menarik dari ArrayList untuk mencegah kesalahan casting. Sekarang orang menggunakan objek, membuat ArrayList tidak lagi diperlukan.
Beralih
1
saya memberi +1 ke justifikasi tetapi Anda masih dapat melakukannya jika (num int) {} ke daftar array Anda untuk menghindari kesalahan
Mina Gabriel
Cegah kesalahan casting dan overhead tinju. Cukup banyak alasan untuk obat generik secara umum.
rawa
26
Untuk menambah poin di atas. Menggunakan ArrayListsistem operasi 64bit membutuhkan memori 2x daripada menggunakan sistem operasi 32bit. Sementara itu, daftar generik List<T>akan menggunakan banyak memori rendah daripada ArrayList.
misalnya jika kita menggunakan ArrayList19MB dalam 32-bit, itu akan membutuhkan 39MB dalam 64-bit. Tetapi jika Anda memiliki daftar generik List<int>8MB dalam 32-bit, ia hanya membutuhkan 8.1MB dalam 64-bit, yang merupakan perbedaan 481% jika dibandingkan dengan ArrayList.
itu hanya berlaku untuk menyimpan tipe nilai, bukan tipe referensi. perbedaannya adalah karena daftar array hanya dapat berisi pointer, dan data itu sendiri perlu disimpan di tempat lain. Di sisi lain, tipe nilai dapat disimpan langsung dalam daftar.
Rasmus Damgaard Nielsen
19
Perbedaan lain yang ditambahkan adalah sehubungan dengan Sinkronisasi Utas.
ArrayListmenyediakan beberapa keamanan thread melalui properti Synchronized, yang mengembalikan pembungkus aman thread di sekitar koleksi. Pembungkus bekerja dengan mengunci seluruh koleksi pada setiap operasi tambah atau hapus. Oleh karena itu, setiap utas yang mencoba mengakses koleksi harus menunggu gilirannya mengambil satu kunci. Ini tidak dapat diskalakan dan dapat menyebabkan penurunan kinerja yang signifikan untuk koleksi besar.
List<T>tidak menyediakan sinkronisasi utas apa pun; kode pengguna harus memberikan semua sinkronisasi ketika item ditambahkan atau dihapus pada banyak utas secara bersamaan.
Saya tidak mengatakan Anda harus menggunakan ArrayListjika itu bisa dihindari, tetapi ini adalah alasan yang konyol. Bagaimanapun, bungkusnya sepenuhnya opsional; jika Anda tidak perlu mengunci atau jika Anda membutuhkan lebih banyak kontrol granular, jangan gunakan pembungkus.
Thorarin
1
Jika Anda ingin keamanan utas saya sarankan melihat namespace System.Collections.Concurrent sebelum mempertimbangkan ArrayList.
Ykok
15
Jawaban sederhana adalah,
ArrayList adalah Non-Generik
Ini adalah Tipe Objek, jadi Anda bisa menyimpan semua tipe data ke dalamnya.
Anda dapat menyimpan nilai apa pun (tipe nilai atau tipe referensi) seperti string, int, karyawan, dan objek di ArrayList. (Catatan dan)
Boxing dan Unboxing akan terjadi.
Tidak mengetik aman.
Itu lebih tua.
Daftar adalah Generik
Ini adalah Type of Type, sehingga Anda dapat menentukan T pada waktu berjalan.
Anda dapat menyimpan nilai Tipe T (string atau int atau karyawan atau objek) hanya berdasarkan deklarasi. (Catatan atau)
Kinerja telah disebutkan dalam beberapa jawaban sebagai faktor pembeda, tetapi untuk mengatasi " Berapa banyak lebih lambat ArrayList? "Dan" Mengapa lebih lambat secara keseluruhan?”, Lihat di bawah.
Kapan pun tipe nilai digunakan sebagai elemen, kinerja akan turun secara dramatis ArrayList. Pertimbangkan kasus penambahan elemen. Karena tinju terjadi - karena ArrayListTambah hanya membutuhkan objectparameter - Pengumpul Sampah akan terpicu untuk melakukan lebih banyak pekerjaan daripada dengan List<T>.
Berapa perbedaan waktu? Setidaknya beberapa kali lebih lambat dibandingkan dengan List<T>. Lihatlah apa yang terjadi dengan kode yang menambahkan nilai 10 mil int ke ArrayListvs List<T>:
Itu perbedaan waktu lari 5x di kolom 'Mean', disorot dengan warna kuning. Perhatikan juga perbedaan dalam jumlah pengumpulan sampah yang dilakukan untuk masing-masing, disorot dalam warna merah (tidak ada GC / 1000 berjalan).
Menggunakan profiler untuk melihat apa yang terjadi dengan cepat menunjukkan bahwa sebagian besar waktu dihabiskan untuk melakukan GCs , bukan benar-benar menambahkan elemen. Bilah coklat di bawah mewakili aktivitas Pemblokir Sampah yang menghalangi:
Temuan serupa ada di “CLR via C #” oleh Jeffrey Richter. Dari bab 12 (Generik):
[…] Ketika saya mengkompilasi dan menjalankan rilis build (dengan optimisasi dihidupkan) dari program ini di komputer saya, saya mendapatkan output berikut.
Output di sini menunjukkan bahwa menggunakan algoritma Daftar generik dengan tipe Int32 jauh lebih cepat daripada menggunakan algoritma ArrayList non-generik dengan Int32. Faktanya, perbedaannya sangat fenomenal: 1,6 detik versus hampir 11 detik. Itu ~ 7 kali lebih cepat ! Selain itu, menggunakan tipe nilai (Int32) dengan ArrayList menyebabkan banyak operasi tinju terjadi, yang menghasilkan 390 pengumpulan sampah. Sementara itu, algoritma Daftar membutuhkan 6 koleksi sampah.
Saya pikir, perbedaan antara ArrayListdan List<T>adalah:
List<T>, di mana T adalah tipe-nilai lebih cepat dari ArrayList. Ini karena List<T>menghindari tinju / unboxing (di mana T adalah tipe-nilai).
Banyak sumber mengatakan - biasanya ArrayListdigunakan hanya untuk kompatibilitas mundur. (bukan perbedaan nyata, tapi saya pikir ini adalah catatan penting).
Refleksi lebih mudah dengan nongeneric ArrayListkemudianList<T>
ArrayListmemiliki IsSynchronizedproperti. Jadi, mudah untuk membuat dan menggunakan sinkronisasi ArrayList. Saya tidak menemukan IsSynchronizedproperti untuk List<T>. Perlu diingat juga bahwa jenis sinkronisasi ini relatif tidak efisien, msdn ):
var arraylist =newArrayList();var arrayListSyncronized =ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");varlist=newList<object>();var listSyncronized =ArrayList.Synchronized(list);Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such propConsole.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayListmemiliki ArrayList.SyncRootproperti yang dapat digunakan untuk sinkronisasi ( msdn ). List<T>belum memiliki SyncRootproperti, jadi dalam konstruksi berikut Anda perlu menggunakan beberapa objek jika Anda menggunakan List<T>:
ArrayList myCollection =newArrayList();lock(myCollection.SyncRoot)// ofcourse you can use another object for this goal{foreach(object item in myCollection){// ...}}
Seperti disebutkan dalam dokumentasi .NET Framework
Kami tidak menyarankan Anda menggunakan ArrayListkelas untuk pengembangan baru. Sebagai gantinya, kami menyarankan Anda menggunakan List<T>
kelas generik . The ArrayListkelas dirancang untuk menahan koleksi heterogen benda. Namun, itu tidak selalu menawarkan kinerja terbaik. Sebagai gantinya, kami merekomendasikan yang berikut:
Untuk koleksi objek yang heterogen, gunakan tipe List<Object>(dalam C #) atau List(Of Object)(dalam Visual Basic).
Untuk koleksi objek yang homogen, gunakan List<T>kelas.
Menggunakan "Daftar" Anda dapat mencegah kesalahan casting. Sangat berguna untuk menghindari kesalahan casting runtime.
Contoh:
Di sini (menggunakan ArrayList) Anda dapat mengkompilasi kode ini tetapi Anda akan melihat kesalahan eksekusi nanti.
// Create a new ArrayListSystem.Collections.ArrayList mixedList =newSystem.Collections.ArrayList();// Add some numbers to the list
mixedList.Add(7);
mixedList.Add(21);// Add some strings to the list
mixedList.Add("Hello");
mixedList.Add("This is going to be a problem");System.Collections.ArrayList intList =newSystem.Collections.ArrayList();System.Collections.ArrayList strList =newSystem.Collections.ArrayList();foreach(object obj in mixedList){if(obj.GetType().Equals(typeof(int))){
intList.Add(obj);}elseif(obj.GetType().Equals(typeof(string))){
strList.Add(obj);}else{// error.}}
Apa yang ditambahkan di luar jawaban yang diberikan tiga tahun sebelumnya? Teksnya hampir sama verbatim, tanpa menautkan ke sumbernya, tanpa memformat dengan benar, dll.
Douglas Zare
-3
Bagi saya ini semua tentang mengetahui data Anda. Jika saya terus memperluas kode saya berdasarkan efisiensi, saya harus memilih opsi Daftar sebagai cara menguraikan data saya tanpa langkah selalu perlu bertanya-tanya tentang jenis, terutama 'Jenis Kustom'. Jika mesin memahami perbedaan dan dapat menentukan pada itu pada jenis data apa saya benar-benar berurusan dengan lalu mengapa saya harus menghalangi dan membuang waktu melalui perputaran penentuan 'JIKA KEMUDIAN LAIN'? Filosofi saya adalah membiarkan mesin bekerja untuk saya alih-alih saya mengerjakan mesin? Mengetahui perbedaan unik dari berbagai perintah kode objek berjalan jauh dalam membuat kode Anda efisien.
List<>
secara umum, sementara yang itu bertanyaList<object>
secara spesifikJawaban:
Ya, cukup banyak.
List<T>
adalah kelas generik. Ini mendukung menyimpan nilai-nilai dari jenis tertentu tanpa casting ke atau dariobject
(yang akan menyebabkan tinju / unboxing overhead ketikaT
merupakan tipe nilai dalamArrayList
case).ArrayList
hanya menyimpanobject
referensi. Sebagai kumpulan generik,List<T>
mengimplementasikanIEnumerable<T>
antarmuka generik dan dapat digunakan dengan mudah di LINQ (tanpa memerlukan apa punCast
atauOfType
panggilan).ArrayList
milik hari-hari dimana C # tidak memiliki obat generik. Sudah usang mendukungList<T>
. Anda tidak boleh menggunakanArrayList
kode baru yang menargetkan .NET> = 2.0 kecuali Anda harus berinteraksi dengan API lama yang menggunakannya.sumber
ArrayList
saat runtime. Namun secara statis, itu akan membutuhkan para pemainArrayList
.Menggunakan
List<T>
Anda dapat mencegah kesalahan casting. Sangat berguna untuk menghindari kesalahan casting runtime .Contoh:
Di sini (menggunakan
ArrayList
) Anda dapat mengkompilasi kode ini tetapi Anda akan melihat kesalahan eksekusi nanti.Jika Anda menggunakan
List
, Anda menghindari kesalahan ini:Referensi: MSDN
sumber
Untuk menambah poin di atas. Menggunakan
ArrayList
sistem operasi 64bit membutuhkan memori 2x daripada menggunakan sistem operasi 32bit. Sementara itu, daftar generikList<T>
akan menggunakan banyak memori rendah daripadaArrayList
.misalnya jika kita menggunakan
ArrayList
19MB dalam 32-bit, itu akan membutuhkan 39MB dalam 64-bit. Tetapi jika Anda memiliki daftar generikList<int>
8MB dalam 32-bit, ia hanya membutuhkan 8.1MB dalam 64-bit, yang merupakan perbedaan 481% jika dibandingkan dengan ArrayList.Sumber: ArrayList vs. generik untuk tipe primitif dan 64-bit
sumber
Perbedaan lain yang ditambahkan adalah sehubungan dengan Sinkronisasi Utas.
Info lebih lanjut di sini Utas Sinkronisasi di Framework .Net
sumber
ArrayList
jika itu bisa dihindari, tetapi ini adalah alasan yang konyol. Bagaimanapun, bungkusnya sepenuhnya opsional; jika Anda tidak perlu mengunci atau jika Anda membutuhkan lebih banyak kontrol granular, jangan gunakan pembungkus.Jawaban sederhana adalah,
ArrayList adalah Non-Generik
Daftar adalah Generik
Contoh:
Silakan baca dokumen resmi Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
Catatan : Anda harus tahu Generik sebelum memahami perbedaannya: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
sumber
ArrayList
adalah koleksi dari berbagai jenis data sedangkanList<>
koleksi dari jenis yang sama dari depedencties sendiri.sumber
ArrayList
bukan tipe aman sedangkanList<T>
tipe aman. Sederhana :).sumber
Kinerja telah disebutkan dalam beberapa jawaban sebagai faktor pembeda, tetapi untuk mengatasi " Berapa banyak lebih lambat
ArrayList
? "Dan" Mengapa lebih lambat secara keseluruhan?”, Lihat di bawah.Kapan pun tipe nilai digunakan sebagai elemen, kinerja akan turun secara dramatis
ArrayList
. Pertimbangkan kasus penambahan elemen. Karena tinju terjadi - karenaArrayList
Tambah hanya membutuhkanobject
parameter - Pengumpul Sampah akan terpicu untuk melakukan lebih banyak pekerjaan daripada denganList<T>
.Berapa perbedaan waktu? Setidaknya beberapa kali lebih lambat dibandingkan dengan
List<T>
. Lihatlah apa yang terjadi dengan kode yang menambahkan nilai 10 mil int keArrayList
vsList<T>
:Itu perbedaan waktu lari 5x di kolom 'Mean', disorot dengan warna kuning. Perhatikan juga perbedaan dalam jumlah pengumpulan sampah yang dilakukan untuk masing-masing, disorot dalam warna merah (tidak ada GC / 1000 berjalan).
Menggunakan profiler untuk melihat apa yang terjadi dengan cepat menunjukkan bahwa sebagian besar waktu dihabiskan untuk melakukan GCs , bukan benar-benar menambahkan elemen. Bilah coklat di bawah mewakili aktivitas Pemblokir Sampah yang menghalangi:
Saya telah menulis analisis terperinci tentang apa yang terjadi dengan
ArrayList
skenario di atas di sini https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .Temuan serupa ada di “CLR via C #” oleh Jeffrey Richter. Dari bab 12 (Generik):
sumber
Saya pikir, perbedaan antara
ArrayList
danList<T>
adalah:List<T>
, di mana T adalah tipe-nilai lebih cepat dariArrayList
. Ini karenaList<T>
menghindari tinju / unboxing (di mana T adalah tipe-nilai).ArrayList
digunakan hanya untuk kompatibilitas mundur. (bukan perbedaan nyata, tapi saya pikir ini adalah catatan penting).ArrayList
kemudianList<T>
ArrayList
memilikiIsSynchronized
properti. Jadi, mudah untuk membuat dan menggunakan sinkronisasiArrayList
. Saya tidak menemukanIsSynchronized
properti untukList<T>
. Perlu diingat juga bahwa jenis sinkronisasi ini relatif tidak efisien, msdn ):ArrayList
memilikiArrayList.SyncRoot
properti yang dapat digunakan untuk sinkronisasi ( msdn ).List<T>
belum memilikiSyncRoot
properti, jadi dalam konstruksi berikut Anda perlu menggunakan beberapa objek jika Anda menggunakanList<T>
:sumber
Seperti disebutkan dalam dokumentasi .NET Framework
Lihat juga koleksi non-generik tidak boleh digunakan
sumber
Menggunakan "Daftar" Anda dapat mencegah kesalahan casting. Sangat berguna untuk menghindari kesalahan casting runtime.
Contoh:
Di sini (menggunakan ArrayList) Anda dapat mengkompilasi kode ini tetapi Anda akan melihat kesalahan eksekusi nanti.
sumber
Bagi saya ini semua tentang mengetahui data Anda. Jika saya terus memperluas kode saya berdasarkan efisiensi, saya harus memilih opsi Daftar sebagai cara menguraikan data saya tanpa langkah selalu perlu bertanya-tanya tentang jenis, terutama 'Jenis Kustom'. Jika mesin memahami perbedaan dan dapat menentukan pada itu pada jenis data apa saya benar-benar berurusan dengan lalu mengapa saya harus menghalangi dan membuang waktu melalui perputaran penentuan 'JIKA KEMUDIAN LAIN'? Filosofi saya adalah membiarkan mesin bekerja untuk saya alih-alih saya mengerjakan mesin? Mengetahui perbedaan unik dari berbagai perintah kode objek berjalan jauh dalam membuat kode Anda efisien.
Tom Johnson (Satu Entri ... Satu Pintu Keluar)
sumber