Was ist der Unterschied zwischen ArrayListund List<>in C #?
Hat nur List<>ein Typ eine Weile ArrayListnicht?
List<>im Allgemeinen, während das List<object>speziell fragt
Was ist der Unterschied zwischen ArrayListund List<>in C #?
Hat nur List<>ein Typ eine Weile ArrayListnicht?
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 Tes sich in diesem ArrayListFall um einen Werttyp handelt ). ArrayListspeichert einfach objectReferenzen. Als generische Sammlung, List<T>implementiert die generische IEnumerable<T>Schnittstelle und kann leicht in LINQ verwendet werden (ohne zu erfordern Castoder OfTypeAnruf).
ArrayListgehört zu den Tagen, in denen C # keine Generika hatte. Es ist zugunsten von veraltet List<T>. Sie sollten keinen ArrayListneuen Code verwenden, der auf .NET> = 2.0 abzielt, es sei denn, Sie müssen eine Schnittstelle mit einer alten API herstellen, die ihn verwendet.
ArrayListzur 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 ArrayListim 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 ArrayList19 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.
ArrayListBietet 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
ArrayListwenn 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/
ArrayListist die Sammlung von Daten verschiedener Arten, während List<>die Sammlung von ähnlichen Arten seiner eigenen Abhängigkeiten ist.
ArrayListsind 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 objectParameter 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 ArrayListvs 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 ArrayListhier 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 ArrayListund 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).ArrayListnur aus Gründen der Abwärtskompatibilität verwendet. (ist kein wirklicher Unterschied, aber ich denke, es ist ein wichtiger Hinweis).ArrayListdannList<T>ArrayListhat IsSynchronizedEigentum. So ist es einfach, synchronisiert zu erstellen und zu verwenden ArrayList. Ich habe keine IsSynchronizedImmobilie 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 propArrayListhat eine ArrayList.SyncRootEigenschaft, die zur Synchronisation verwendet werden kann ( msdn ). List<T>hat keine SyncRootEigenschaft, 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
ArrayListKlasse für Neuentwicklungen zu verwenden. Stattdessen empfehlen wir Ihnen, die generischeList<T>Klasse zu verwenden. DieArrayListKlasse 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)