ArrayList vs Liste <> in C #


412

Arasındaki fark nedir ArrayListve List<>C #?

Sadece List<>bir türü ArrayListvar değil mi?



5
Bu yakın bir soru ama bence tam olarak yinelenmiyor. Bu List<>genel olarak soruyor , bu da List<object>özellikle soruyor
goodeye

Bu çok yararlı blog bulundu, yardımcı olabilir. Bağlantıyı paylaşmam gerektiğini düşündüm: fintechexplained.blogspot.co.uk/2017/07/…
InfoLearner

Yanıtlar:


533

Evet, hemen hemen. List<T>genel bir sınıftır. Belirli bir tipteki değerlerin döküm yapılmadan veya gönderilmeden depolanmasını destekler object(bu T, ArrayListdurumda bir değer türü olduğunda boks / kutudan çıkarma yüküne neden olur ). ArrayListbasitçe objectreferansları saklar . Genel bir koleksiyon olarak, List<T>genel IEnumerable<T>arayüzü uygular ve LINQ'da (herhangi bir çağrı Castveya OfTypeçağrı gerektirmeden ) kolayca kullanılabilir .

ArrayListC # 'ın jenerik içermediği günlere aittir. Lehine reddedildi List<T>. Bunu ArrayListkullanan eski bir API ile arayüz kurmak zorunda kalmadıkça .NET> = 2.0'ı hedefleyen yeni kodlarda kullanmamalısınız.


Neden "boks" değil "boks" kullandığınızı açıklar mısınız? Burada ne boks var? Nesneler tahsis edilmiş / serbest bırakılmış mı?
Benjamin Gruenbaum

2
@BenjaminGruenbaum Dökümün daha genel olacağı konusunda haklısınız. Bununla birlikte, çalışma zamanında gerçek fark değer türleriyle uğraşırken ("boks" yazdığımda varsaydığım şey). Referans türleri için, davranış ArrayListçalışma zamanında etkin olarak aynıdır . Statik olarak, bununla birlikte bir oyuncu kadrosu gerekir ArrayList.
Mehrdad Afshari

ArrayList örtük olarak izin verir, çünkü çerçeve T "nesne" türüne kısıtlamak gerekip gerekmediğini merak ediyordum.
rajibdotnet

Türlenmemiş koleksiyonların kullanımdan kaldırılmasıyla ilgili olarak bkz. Zararlı
Olarak Kabul Edilen

@ Ant_222, bu blog yaklaşık 15 yıl önce yazıldı. Bence son on yıldaki kanıtlar jeneriklerin zararlı olmadığını göstermiştir. :)
Scott Adams

101

Kullanarak List<T>döküm hatalarını önleyebilirsiniz. Bir çalışma zamanı döküm hatasını önlemek için çok kullanışlıdır .

Misal:

Burada (kullanarak ArrayList) bu kodu derleyebilirsiniz, ancak daha sonra bir yürütme hatası göreceksiniz.

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
}

Kullanırsanız List, şu hatalardan kaçınırsınız:

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;
}

Referans: MSDN


Yayınlama hatalarını önlemek için ArrayList'ten çektiğinizde türü kontrol edebilirsiniz. Artık insanlar nesne kullanıyor, ArrayList artık gerekmiyor.
Anahtarı

1
i + gerekçesi + 1 ama yine de yapabilirsiniz (num int) {} hataları önlemek için dizi listenize
Mina Gabriel

Döküm hatalarını ve boks yükünü önleyin. Genel olarak jeneriklerin nedenleri.
marsze

26

Yukarıdaki noktalara eklemek için. Kullanılması ArrayList64bit işletim sisteminde 32 bit işletim sisteminde kullanmak yerine 2x bellek alır. Bu arada, genel liste List<T>çok daha az bellek kullanır ArrayList.

örneğin ArrayList, 32 bit'te 19 MB'lık bir a kullanırsak 64 bit'te 39 MB gerekir. Ancak List<int>32-bit'de 8MB'lık genel bir listeniz varsa , 64-bit'de sadece 8.1MB alır, bu da ArrayList ile karşılaştırıldığında% 481'lik bir farktır.

Kaynak: İlkel türler ve 64 bit için ArrayList'in genel Listesi


5
bu yalnızca değer türlerini depolamak için geçerlidir, referans türlerini değil. fark, bir arraylistin sadece işaretçiler içerebilmesi ve verilerin kendisinin başka bir yerde saklanması gerektiğidir. Öte yandan, değer türleri doğrudan bir listede saklanabilir.
Rasmus Damgaard Nielsen

19

Eklenecek bir diğer fark, Konu Senkronizasyonu ile ilgilidir.

ArrayList, koleksiyonun çevresinde bir iş parçacığı için güvenli sarmalayıcı döndüren Synchronized özelliği aracılığıyla iş parçacığı güvenliği sağlar. Sargı, toplama veya çıkarma işlemlerinin tümünde tüm koleksiyonu kilitleyerek çalışır. Bu nedenle, koleksiyona erişmeye çalışan her iş parçacığı sırayla bir kilit almak için beklemek gerekir. Bu ölçeklenebilir değildir ve büyük koleksiyonlar için önemli performans düşüşüne neden olabilir.

List<T>herhangi bir evre senkronizasyonu sağlamaz; eşzamanlı olarak birden çok iş parçacığına öğe eklendiğinde veya kaldırıldığında kullanıcı kodu tüm eşitlemeyi sağlamalıdır.

Daha fazla bilgi için .Net Framework'te Konu Senkronizasyonu


Önlenebilirse kullanmanız gerektiğini söylemiyorum ArrayList, ama bu aptalca bir sebep. Sonuçta sargı tamamen isteğe bağlıdır; Kilitlemeye ihtiyacınız yoksa veya daha ayrıntılı bir denetime ihtiyacınız varsa, ambalajı kullanmayın.
Thorarin

1
İş parçacığı güvenliği istiyorsanız ArrayList'i düşünmeden önce System.Collections.Concurrent ad boşluğuna bakmanızı öneririm.
Ykok

15

Basit Yanıt,

ArrayList Genel Değildir

  • Bu bir Nesne Türüdür, böylece içine herhangi bir veri türü kaydedebilirsiniz.
  • ArrayList'te dize, int, çalışan ve nesne gibi herhangi bir değeri (değer türü veya referans türü) saklayabilirsiniz. (Not ve)
  • Boks ve Kutudan Çıkarma gerçekleşecek.
  • Güvenli yazmayın.
  • Daha eskidir.

Liste Geneldir

  • Bu bir Tür türüdür, bu nedenle çalışma zamanında T'yi belirleyebilirsiniz.
  • Bildirime dayanarak yalnızca T Tipi değerini (dize veya int veya çalışan veya nesne) saklayabilirsiniz. (Not veya)
  • Boks ve Kutudan Çıkarma gerçekleşmeyecek.
  • Güvenli yazın.
  • Daha yeni.

Misal:

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

Lütfen Microsoft resmi belgesini okuyun : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/

resim açıklamasını buraya girin

Not : Farkı anlamadan önce Generics'i bilmelisiniz: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/


4

ArrayListfarklı türdeki verilerin toplanmasıdır, oysa List<>kendi bağımlılıklarının benzer türlerinin toplanmasıdır.



2

Performans birkaç cevapta farklılaştırıcı bir faktör olarak belirtilmiştir, ancak “ Ne kadar yavaştır ArrayList? ”Ve“ Genel olarak neden daha yavaş? ”, Aşağıya bakın.

Değer türleri öğe olarak kullanıldığında, performans önemli ölçüde düşer ArrayList. Yalnızca öğe ekleme konusunu düşünün. Boks devam ettiği için - ArrayList's Add sadece objectparametre alır gibi - Çöp Toplayıcı olduğundan çok daha fazla iş yapmak için tetiklenir List<T>.

Zaman farkı ne kadar? En az birkaç kat daha yavaş List<T>. Sadece kod 10 mil int değerler ekleyerek ile ne bir göz atın ArrayListvs List<T>: resim açıklamasını buraya girin

Bu , Sarı ile vurgulanan 'Ortalama' sütununda 5x'lik bir çalışma süresi farkıdır . Ayrıca, her biri için kırmızı renkle vurgulanmış (GC / 1000 çalıştırma sayısı) yapılan çöp toplama sayısındaki farka dikkat edin.

Neler olup bittiğini hızlı bir şekilde görmek için bir profil oluşturucu kullanmak, çoğu zaman aslında öğe eklemenin aksine GC'leri harcadığını gösterir . Aşağıdaki kahverengi çubuklar Çöp Toplayıcı etkinliğinin engellenmesini temsil eder: resim açıklamasını buraya girin

Yukarıdaki ArrayListsenaryoda neler olup bittiğinin ayrıntılı bir analizini burada yazdım https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .

Benzer bulgular Jeffrey Richter'in “C # üzerinden CLR” de. Bölüm 12'den (Jenerikler):

[…] Derleme ve bilgisayarımda bu programın bir sürüm derleme (optimizasyon açıkken) çalıştırdığınızda, aşağıdaki çıktıyı alıyorum.

00: 00: 01.6246959 (KR = 6) Liste <Int32>
00: 00: 10,8555008 (KR = 390) ArrayList Int32
00: 00: 02.5427847 (KR = 4) listesi <String>
00: 00: 02.7944831 (KR = 7 ) Dizi Dizisi

Buradaki çıktı, Int32 türüyle genel Liste algoritmasının kullanılmasının, genel olmayan ArrayList algoritmasını Int32 ile kullanmaktan çok daha hızlı olduğunu göstermektedir. Aslında, fark olağanüstü: 1,6 saniye ve neredeyse 11 saniye. Bu ~ 7 kat daha hızlı ! Buna ek olarak, ArrayList ile bir değer türü (Int32) kullanmak, çok fazla boks işleminin oluşmasına neden olur ve bu da 390 çöp toplama ile sonuçlanır. Bu arada, Liste algoritması 6 çöp toplama gerektiriyordu.


1

Ben arasındaki farklar, düşünmek ArrayListve List<T>şunlardır:

  1. List<T>, burada T değer türünden daha hızlıdır ArrayList. Bunun nedeni List<T>, boks / kutudan kaçınmaktır (burada T değer tipidir).
  2. Birçok kaynak söylüyor - genellikle ArrayListsadece geriye dönük uyumluluk için kullanılır. (gerçek bir fark değil, ama önemli bir not olduğunu düşünüyorum).
  3. Dijital olmayanlarla yansıma ArrayListo zaman daha kolaydırList<T>
  4. ArrayListsahiptir IsSynchronizedözelliğini. Bu nedenle, senkronize edilmiş oluşturmak ve kullanmak kolaydır ArrayList. İçin IsSynchronizedmülk bulamadım List<T>. Ayrıca bu tür senkronizasyonun göreceli olarak yetersiz olduğunu unutmayın, 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. ArrayListyer alır ArrayList.SyncRootsyncronisation (kullanılabilir özelliği msdn ). List<T>sahip değil SyncRootmülkiyet, böylece aşağıdaki yapımında kullandığınız takdirde bazı nesne kullanmak gerekmez List<T>:

    ArrayList myCollection = new ArrayList();
    lock(myCollection.SyncRoot) //  ofcourse you can use another object for this goal
    {
        foreach (object item in myCollection)
        {
            // ...
        }
    }

0

.NET Framework belgelerinde belirtildiği gibi

ArrayListYeni geliştirme için sınıfı kullanmanızı önermiyoruz . Bunun yerine, genel List<T> sınıfı kullanmanızı öneririz . ArrayListSınıf nesnelerinin heterojen koleksiyonları tutmak için tasarlanmıştır. Ancak, her zaman en iyi performansı sunmaz. Bunun yerine, aşağıdakileri öneririz:

  • Heterojen bir nesne koleksiyonu için, List<Object>(C #) veya List(Of Object)(Visual Basic) türünü kullanın.
  • Homojen bir nesne koleksiyonu için List<T>sınıfı kullanın .

Ayrıca bkz. Jenerik olmayan koleksiyonlar kullanılmamalıdır

tablo, genel olmayan toplama türlerinin genel eşleriyle nasıl değiştirilebileceğini gösterir


-2

"Liste" kullanarak döküm hatalarını önleyebilirsiniz. Bir çalışma zamanı döküm hatasını önlemek için çok kullanışlıdır.

Misal:

Burada (ArrayList kullanarak) bu kodu derleyebilirsiniz, ancak daha sonra bir yürütme hatası görürsünüz.

    // 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.
        }
    }

Bu, termas'ın üç yıl önce verdiği cevabın ötesine ne katıyor? Kaynağa bağlantı vermeden, düzgün biçimlendirmeden vb. Neredeyse aynı metne sahiptir.
Douglas Zare

-3

Benim için her şey verilerinizi bilmekle ilgili. Kodumu verimlilik temelinde genişletmeye devam edersem, her zaman türleri, özellikle de 'Özel Türleri' merak etmenin gereksiz adımı olmadan verilerimin deşifre edilmesi için Liste seçeneğini seçmeliyim. Makine farkı anlar ve aslında ne tür verilerle uğraştığımı belirleyebiliyorsa, neden 'BAŞKA EĞER İSE' tespitlerinin dönmeleriyle neden yol alıp zaman harcamalıyım? Felsefem, makine üzerinde çalışmak yerine makinenin benim için çalışmasına izin vermektir. Farklı nesne kodu komutlarının benzersiz farklılıklarını bilmek, kodunuzu verimli hale getirmenin uzun bir yoludur.

Tom Johnson (Bir Giriş ... Bir Çıkış)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.