ArrayList vs Daftar <> dalam C #


412

Apa perbedaan antara ArrayListdan List<>di C #?

Apakah hanya yang List<>memiliki tipe sementara ArrayListtidak?


5
kemungkinan duplikat dari ArrayList vs List <object>
John Saunders

5
Ini pertanyaan yang dekat, tapi saya pikir tidak persis sama. Ini menanyakan List<>secara umum, sementara yang itu bertanya List<object>secara spesifik
selamat tinggal

Menemukan blog yang sangat membantu ini, mungkin membantu. Pikir saya harus berbagi tautan: fintechexplained.blogspot.co.uk/2017/07/...
InfoLearner

Jawaban:


533

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.
rajibdotnet

Mengenai penghentian koleksi yang tidak diketik, lihat Generics Dianggap Berbahaya
Ant_222

@ 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 = new ArrayList();
array1.Add(1);
array1.Add("Pony"); //No error at compile process
int total = 0;
foreach (int num in array1)
{
 total += num; //-->Runtime Error
}

Jika Anda menggunakan List, Anda menghindari kesalahan ini:

List<int> list1 = new List<int>();
list1.Add(1);
//list1.Add("Pony"); //<-- Error at compile process
int total = 0;
foreach (int num in list1 )
{
 total += num;
}

Referensi: MSDN


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.

Sumber: ArrayList vs. generik untuk tipe primitif dan 64-bit


5
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.

Info lebih lanjut di sini Utas Sinkronisasi di Framework .Net


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)
  • Boxing dan Unboxing tidak akan terjadi.
  • Ketik aman.
  • Itu lebih baru.

Contoh:

ArrayList arrayList = new ArrayList();
List<int> list = new List<int>();

arrayList.Add(1);
arrayList.Add("String");
arrayList.Add(new object());


list.Add(1);
list.Add("String");                 // Compile-time Error
list.Add(new object());             // Compile-time Error

Silakan baca dokumen resmi Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/

masukkan deskripsi gambar di sini

Catatan : Anda harus tahu Generik sebelum memahami perbedaannya: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/


4

ArrayListadalah koleksi dari berbagai jenis data sedangkan List<>koleksi dari jenis yang sama dari depedencties sendiri.



2

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>: masukkan deskripsi gambar di sini

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: masukkan deskripsi gambar di sini

Saya telah menulis analisis terperinci tentang apa yang terjadi dengan ArrayListskenario 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):

[…] Ketika saya mengkompilasi dan menjalankan rilis build (dengan optimisasi dihidupkan) dari program ini di komputer saya, saya mendapatkan output berikut.

00:00: 01.6246959 (GCs = 6) Daftar <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayDaftar Int32
00: 00: 02.5427847 (GCs = 4) Daftar <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of String

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.


1

Saya pikir, perbedaan antara ArrayListdan List<T>adalah:

  1. 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).
  2. Banyak sumber mengatakan - biasanya ArrayListdigunakan hanya untuk kompatibilitas mundur. (bukan perbedaan nyata, tapi saya pikir ini adalah catatan penting).
  3. Refleksi lebih mudah dengan nongeneric ArrayListkemudianList<T>
  4. 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 = new ArrayList();
    var arrayListSyncronized = ArrayList.Synchronized(arraylist
    Console.WriteLine($"syncronized {arraylist.IsSynchronized}");
    Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");
    
    var list = new List<object>();
    var listSyncronized = ArrayList.Synchronized(list);
    Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
    Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
  5. 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 = new ArrayList();
    lock(myCollection.SyncRoot) //  ofcourse you can use another object for this goal
    {
        foreach (object item in myCollection)
        {
            // ...
        }
    }

0

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.

Lihat juga koleksi non-generik tidak boleh digunakan

tabel menunjukkan bagaimana tipe pengumpulan non-generik dapat diganti oleh rekan-rekan generik mereka


-2

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 ArrayList


    System.Collections.ArrayList mixedList = new System.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 = new System.Collections.ArrayList();
    System.Collections.ArrayList strList = new System.Collections.ArrayList();


    foreach (object obj in mixedList)
    {
        if (obj.GetType().Equals(typeof(int)))
        {
            intList.Add(obj);
        }
        else if (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.

Tom Johnson (Satu Entri ... Satu Pintu Keluar)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.