Qual è la differenza tra ArrayList
e List<>
in C #?
È solo quello che List<>
ha un tipo mentre ArrayList
no?
List<>
in generale, mentre quello chiede List<object>
specificamente
Qual è la differenza tra ArrayList
e List<>
in C #?
È solo quello che List<>
ha un tipo mentre ArrayList
no?
List<>
in generale, mentre quello chiede List<object>
specificamente
Risposte:
Sì, praticamente. List<T>
è una classe generica. Supporta la memorizzazione di valori di un tipo specifico senza eseguire il casting da o verso object
(il che avrebbe comportato un sovraccarico di box / unboxing quando si T
tratta di un tipo di valore nel ArrayList
caso). ArrayList
memorizza semplicemente object
riferimenti. Come raccolta generica, List<T>
implementa l' IEnumerable<T>
interfaccia generica e può essere utilizzata facilmente in LINQ (senza richiedere alcuna Cast
o OfType
chiamata).
ArrayList
appartiene ai giorni in cui C # non aveva generici. È deprecato a favore di List<T>
. Non è necessario utilizzare ArrayList
nel nuovo codice destinato a .NET> = 2.0 a meno che non sia necessario interfacciarsi con una vecchia API che lo utilizza.
ArrayList
runtime. Staticamente però, richiederà un cast con ArrayList
.
Usando List<T>
puoi prevenire errori di casting. È molto utile evitare un errore di casting runtime .
Esempio:
Qui (usando ArrayList
) puoi compilare questo codice ma vedrai un errore di esecuzione in seguito.
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
}
Se si utilizza List
, si evitano questi errori:
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;
}
Riferimento: MSDN
Da aggiungere ai punti precedenti. L'utilizzo ArrayList
nel sistema operativo a 64 bit richiede 2x memoria rispetto all'utilizzo nel sistema operativo a 32 bit. Nel frattempo, l'elenco generico List<T>
utilizzerà molta memoria insufficiente rispetto a ArrayList
.
per esempio se usiamo un ArrayList
19 MB a 32 bit, ci vorranno 39 MB a 64 bit. Ma se hai un elenco genericoList<int>
di 8 MB a 32 bit, occorrerebbero solo 8,1 MB a 64 bit, il che è una differenza enorme del 481% rispetto ad ArrayList.
Fonte: ArrayList's vs. Elenco generico per tipi primitivi e 64 bit
Un'altra differenza da aggiungere è rispetto alla sincronizzazione dei thread.
ArrayList
fornisce un po 'di sicurezza dei thread tramite la proprietà Synchronized, che restituisce un wrapper thread-safe attorno alla raccolta. Il wrapper funziona bloccando l'intera raccolta su ogni operazione di aggiunta o rimozione. Pertanto, ogni thread che sta tentando di accedere alla raccolta deve attendere il proprio turno per ottenere un blocco. Questo non è scalabile e può causare un significativo peggioramento delle prestazioni per grandi raccolte.
List<T>
non fornisce alcuna sincronizzazione dei thread; il codice utente deve fornire tutta la sincronizzazione quando gli elementi vengono aggiunti o rimossi contemporaneamente su più thread.
Maggiori informazioni qui Sincronizzazione di thread in .Net Framework
ArrayList
se può essere evitato, ma questa è una ragione sciocca. Il wrapper è del tutto facoltativo dopo tutto; se non è necessario il blocco o se è necessario un controllo più granulare, non utilizzare il wrapper.
La risposta semplice è
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
Si prega di leggere il documento ufficiale di Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
Nota : è necessario conoscere Generics prima di comprendere la differenza: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
sono le raccolte di dati di tipi diversi mentre List<>
è la raccolta di tipi simili di sua proprietà.
ArrayList
non sono sicuri, mentre List<T>
sono sicuri. Semplice :).
Le prestazioni sono già state menzionate in diverse risposte come un fattore di differenziazione, ma per affrontare il " Quanto è più lento ArrayList
? "E" Perché è più lento nel complesso? ", Dai un'occhiata qui sotto.
Ogni volta che i tipi di valore vengono utilizzati come elementi, le prestazioni diminuiscono drasticamente con ArrayList
. Considera il caso di aggiungere semplicemente elementi. A causa della boxe in corso - poiché ArrayList
Aggiungi richiede solo object
parametri - Garbage Collector viene attivato per eseguire molto più lavoro rispetto a List<T>
.
Quanto è la differenza di tempo? Almeno diverse volte più lentamente che con List<T>
. Dai un'occhiata a cosa succede con il codice che aggiunge 10 milioni di valori int a un ArrayList
vs List<T>
:
Questa è una differenza di tempo di esecuzione di 5x nella colonna "Media", evidenziata in giallo. Notare anche la differenza nel numero di raccolte di rifiuti eseguite per ciascuna, evidenziate in rosso (nessun numero di GC / 1000 esecuzioni).
L'uso di un profiler per vedere cosa sta succedendo mostra rapidamente che la maggior parte del tempo viene impiegato per fare GC , invece di aggiungere effettivamente elementi. Le barre marroni in basso rappresentano il blocco dell'attività di Garbage Collector:
Ho scritto un'analisi dettagliata di ciò che accade con lo ArrayList
scenario sopra qui https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .
Risultati simili si trovano in "CLR via C #" di Jeffrey Richter. Dal capitolo 12 (Generics):
[…] Quando compilo ed eseguo una build di rilascio (con le ottimizzazioni attivate) di questo programma sul mio computer, ottengo il seguente output.
00: 00: 01.6246959 (GCs = 6) Elenco <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayList of Int32
00: 00: 02.5427847 (GCs = 4) Elenco <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of StringL'output qui mostra che l'utilizzo dell'algoritmo List generico con il tipo Int32 è molto più veloce rispetto all'uso dell'algoritmo ArrayList non generico con Int32. In effetti, la differenza è fenomenale: 1,6 secondi contro quasi 11 secondi. Questo è ~ 7 volte più veloce ! Inoltre, l'utilizzo di un tipo di valore (Int32) con ArrayList provoca molte operazioni di inscatolamento, con conseguente 390 garbage collection. Nel frattempo, l'algoritmo List richiedeva 6 garbage collection.
Penso che le differenze tra ArrayList
e List<T>
siano:
List<T>
, dove T è di tipo valore è più veloce di ArrayList
. Questo perché List<T>
evita il boxing / unboxing (dove T è di tipo valore).ArrayList
usato solo per compatibilità con le versioni precedenti. (non è una vera differenza, ma penso che sia una nota importante).ArrayList
alloraList<T>
ArrayList
ha IsSynchronized
proprietà. Quindi, è facile da creare e utilizzare sincronizzato ArrayList
. Non ho trovato IsSynchronized
proprietà per List<T>
. Inoltre, tieni presente che questo tipo di sincronizzazione è relativamente inefficiente, 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
ha ArrayList.SyncRoot
proprietà che possono essere utilizzate per la sincronizzazione ( msdn ). List<T>
non ha SyncRoot
proprietà, quindi nella seguente costruzione è necessario utilizzare alcuni oggetti se si utilizza List<T>
:
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
Come menzionato nella documentazione di .NET Framework
Non è consigliabile utilizzare la
ArrayList
classe per nuovi sviluppi. Invece, ti consigliamo di utilizzare laList<T>
classe generica . LaArrayList
classe è progettata per contenere raccolte eterogenee di oggetti. Tuttavia, non offre sempre le migliori prestazioni. Raccomandiamo invece quanto segue:
- Per una raccolta eterogenea di oggetti, utilizzare il tipo
List<Object>
(in C #) oList(Of Object)
(in Visual Basic).- Per una raccolta omogenea di oggetti, utilizzare la
List<T>
classe.
Vedi anche Le raccolte non generiche non devono essere utilizzate
Usando "Elenco" è possibile prevenire errori di trasmissione. È molto utile evitare un errore di casting runtime.
Esempio:
Qui (usando ArrayList) puoi compilare questo codice ma vedrai un errore di esecuzione in seguito.
// 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.
}
}
Per me è tutto sulla conoscenza dei tuoi dati. Se continuo ad espandere il mio codice sulla base dell'efficienza, dovrei scegliere l'opzione Elenco come modo per decifrare i miei dati senza il passaggio inutile di chiedermi sempre i tipi, in particolare i "Tipi personalizzati". Se la macchina capisce la differenza e può determinare su quale tipo di dati sto effettivamente trattando, allora perché dovrei intralciarmi e perdere tempo a passare attraverso le determinazioni di "IF THEN ELSE"? La mia filosofia è quella di lasciare che la macchina funzioni per me invece che lavorare sulla macchina? Conoscere le differenze uniche tra i diversi comandi del codice oggetto aiuta a rendere il codice efficiente.
Tom Johnson (Una voce ... Una uscita)