Was ist der Unterschied zwischen ArrayList
und List<>
in C #?
Hat nur List<>
ein Typ eine Weile ArrayList
nicht?
List<>
im Allgemeinen, während das List<object>
speziell fragt
Was ist der Unterschied zwischen ArrayList
und List<>
in C #?
Hat nur List<>
ein Typ eine Weile ArrayList
nicht?
List<>
im Allgemeinen, während das List<object>
speziell fragt
Antworten:
Ja so ziemlich. List<T>
ist eine generische Klasse. Es unterstützt das Speichern von Werten eines bestimmten Typs ohne Umwandlung in oder von object
(was zu einem Box- / Unboxing-Overhead geführt hätte, wenn T
es sich in diesem ArrayList
Fall um einen Werttyp handelt ). ArrayList
speichert einfach object
Referenzen. Als generische Sammlung, List<T>
implementiert die generische IEnumerable<T>
Schnittstelle und kann leicht in LINQ verwendet werden (ohne zu erfordern Cast
oder OfType
Anruf).
ArrayList
gehört zu den Tagen, in denen C # keine Generika hatte. Es ist zugunsten von veraltet List<T>
. Sie sollten keinen ArrayList
neuen Code verwenden, der auf .NET> = 2.0 abzielt, es sei denn, Sie müssen eine Schnittstelle mit einer alten API herstellen, die ihn verwendet.
ArrayList
zur Laufzeit. Statisch erfordert es jedoch eine Besetzung mit ArrayList
.
Mit können List<T>
Sie Casting-Fehler vermeiden. Es ist sehr nützlich, einen Laufzeit- Casting-Fehler zu vermeiden .
Beispiel:
Hier (mit ArrayList
) können Sie diesen Code kompilieren, aber später wird ein Ausführungsfehler angezeigt.
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
}
Wenn Sie verwenden List
, vermeiden Sie diese Fehler:
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;
}
Referenz: MSDN
Zu den obigen Punkten hinzufügen. Die Verwendung ArrayList
im 64-Bit-Betriebssystem benötigt 2x Speicher als die Verwendung im 32-Bit-Betriebssystem. In der Zwischenzeit benötigt die generische Liste List<T>
viel weniger Speicher als die ArrayList
.
Wenn wir beispielsweise ArrayList
19 MB in 32-Bit verwenden, werden in 64-Bit 39 MB benötigt. Aber wenn Sie eine generische Liste habenList<int>
von 8 MB in 32-Bit haben, werden nur 8,1 MB in 64-Bit benötigt, was im Vergleich zu ArrayList einen Unterschied von 481% darstellt.
Quelle: ArrayList's vs. generic List für primitive Typen und 64-Bit
Ein weiterer Unterschied besteht in der Thread-Synchronisation.
ArrayList
Bietet eine gewisse Thread-Sicherheit durch die Synchronized-Eigenschaft, die einen thread-sicheren Wrapper um die Sammlung zurückgibt. Der Wrapper sperrt die gesamte Sammlung bei jedem Hinzufügen oder Entfernen. Daher muss jeder Thread, der versucht, auf die Sammlung zuzugreifen, warten, bis er an der Reihe ist, um die eine Sperre zu erhalten. Dies ist nicht skalierbar und kann bei großen Sammlungen zu erheblichen Leistungseinbußen führen.
List<T>
bietet keine Thread-Synchronisation; Der Benutzercode muss die gesamte Synchronisierung bereitstellen, wenn Elemente in mehreren Threads gleichzeitig hinzugefügt oder entfernt werden.
Weitere Informationen hier Thread-Synchronisation im .Net Framework
ArrayList
wenn es vermieden werden kann, aber das ist ein dummer Grund. Der Wrapper ist schließlich völlig optional; Wenn Sie keine Sperre benötigen oder eine detailliertere Steuerung benötigen, verwenden Sie den Wrapper nicht.
Einfache Antwort ist,
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
Bitte lesen Sie das offizielle Microsoft-Dokument : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
Hinweis : Sie sollten Generics kennen, bevor Sie den Unterschied verstehen: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
ist die Sammlung von Daten verschiedener Arten, während List<>
die Sammlung von ähnlichen Arten seiner eigenen Abhängigkeiten ist.
ArrayList
sind nicht typsicher, wohingegen List<T>
typsicher sind. Einfach :).
Die Leistung wurde bereits in mehreren Antworten als Differenzierungsfaktor erwähnt, aber um das „ Wie viel langsamer ist das ArrayList
? "Und" Warum ist es insgesamt langsamer?”, Schauen Sie unten.
Immer wenn Werttypen als Elemente verwendet werden, sinkt die Leistung dramatisch mit ArrayList
. Betrachten Sie den Fall des einfachen Hinzufügens von Elementen. Aufgrund des laufenden Boxens - da ArrayList
'Add' nur object
Parameter benötigt - wird der Garbage Collector dazu veranlasst, viel mehr Arbeit als mit auszuführen List<T>
.
Wie groß ist der Zeitunterschied? Mindestens mehrmals langsamer als mit List<T>
. Schauen Sie sich an, was mit Code passiert, der einem ArrayList
vs 10 mil int-Werte hinzufügt List<T>
:
Das ist ein Laufzeitunterschied von 5x in der gelb hervorgehobenen Spalte "Mittelwert". Beachten Sie auch den Unterschied in der Anzahl der jeweils durchgeführten Garbage Collections, die rot hervorgehoben sind (Anzahl der GCs / 1000-Läufe).
Die Verwendung eines Profilers, um schnell zu sehen, was los ist, zeigt, dass die meiste Zeit mit GCs verbracht wird, anstatt tatsächlich Elemente hinzuzufügen. Die braunen Balken unten stellen die blockierende Garbage Collector-Aktivität dar:
Ich habe ArrayList
hier https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ eine detaillierte Analyse der oben beschriebenen Szenarien verfasst .
Ähnliche Ergebnisse finden sich in „CLR via C #“ von Jeffrey Richter. Aus Kapitel 12 (Generika):
[…] Wenn ich einen Release-Build (mit aktivierten Optimierungen) dieses Programms auf meinem Computer kompiliere und ausführe, erhalte ich die folgende Ausgabe.
00: 00: 01.6246959 (GCs = 6) Liste <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayList von Int32
00: 00: 02.5427847 (GCs = 4) Liste <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of StringDie Ausgabe hier zeigt, dass die Verwendung des generischen Listenalgorithmus mit dem Int32-Typ viel schneller ist als die Verwendung des nicht generischen ArrayList-Algorithmus mit Int32. Tatsächlich ist der Unterschied phänomenal: 1,6 Sekunden gegenüber fast 11 Sekunden. Das ist ~ 7 mal schneller ! Darüber hinaus führt die Verwendung eines Werttyps (Int32) mit ArrayList dazu, dass viele Boxvorgänge ausgeführt werden, was zu 390 Speicherbereinigungen führt. In der Zwischenzeit benötigte der List-Algorithmus 6 Garbage Collections.
Ich denke, die Unterschiede zwischen ArrayList
und List<T>
sind:
List<T>
, wobei T ein Werttyp ist, ist schneller als ArrayList
. Dies liegt daran, dass List<T>
Boxen / Unboxing vermieden wird (wobei T ein Werttyp ist).ArrayList
nur aus Gründen der Abwärtskompatibilität verwendet. (ist kein wirklicher Unterschied, aber ich denke, es ist ein wichtiger Hinweis).ArrayList
dannList<T>
ArrayList
hat IsSynchronized
Eigentum. So ist es einfach, synchronisiert zu erstellen und zu verwenden ArrayList
. Ich habe keine IsSynchronized
Immobilie für gefunden List<T>
. Beachten Sie auch, dass diese Art der Synchronisation relativ ineffizient ist ( 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
ArrayList
hat eine ArrayList.SyncRoot
Eigenschaft, die zur Synchronisation verwendet werden kann ( msdn ). List<T>
hat keine SyncRoot
Eigenschaft, daher müssen Sie in der folgenden Konstruktion ein Objekt verwenden, wenn Sie verwenden List<T>
:
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
Wie in der .NET Framework- Dokumentation erwähnt
Wir empfehlen nicht, die
ArrayList
Klasse für Neuentwicklungen zu verwenden. Stattdessen empfehlen wir Ihnen, die generischeList<T>
Klasse zu verwenden. DieArrayList
Klasse ist für heterogene Sammlungen von Objekten ausgelegt. Es bietet jedoch nicht immer die beste Leistung. Stattdessen empfehlen wir Folgendes:
- Verwenden Sie für eine heterogene Sammlung von Objekten den Typ
List<Object>
(in C #) oderList(Of Object)
(in Visual Basic).- Verwenden Sie für eine homogene Sammlung von Objekten die
List<T>
Klasse.
Siehe auch Nicht generische Sammlungen sollten nicht verwendet werden
Mit "Liste" können Sie Casting-Fehler vermeiden. Es ist sehr nützlich, einen Laufzeit-Casting-Fehler zu vermeiden.
Beispiel:
Hier (mit ArrayList) können Sie diesen Code kompilieren, aber später wird ein Ausführungsfehler angezeigt.
// 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.
}
}
Für mich geht es darum, Ihre Daten zu kennen. Wenn ich meinen Code aus Effizienzgründen weiter ausbauen möchte, muss ich die Option Liste auswählen, um meine Daten zu entschlüsseln, ohne mich unnötig über Typen, insbesondere über benutzerdefinierte Typen, zu wundern. Wenn die Maschine den Unterschied versteht und feststellen kann, um welche Art von Daten es sich tatsächlich handelt, warum sollte ich mich dann in den Weg stellen und Zeit damit verschwenden, die Drehungen der Bestimmungen "WENN DANN SONST" zu durchlaufen? Meine Philosophie ist es, die Maschine für mich arbeiten zu lassen, anstatt dass ich an der Maschine arbeite? Die Kenntnis der einzigartigen Unterschiede verschiedener Objektcodebefehle trägt wesentlich dazu bei, Ihren Code so effizient wie möglich zu gestalten.
Tom Johnson (Ein Eintrag ... Ein Ausgang)