Cuál es la diferencia entre ArrayList
y List<>
en C #?
¿Es solo que List<>
tiene un tipo mientras ArrayList
que no lo tiene?
List<>
en general, mientras que ese pregunta List<object>
específicamente
Cuál es la diferencia entre ArrayList
y List<>
en C #?
¿Es solo que List<>
tiene un tipo mientras ArrayList
que no lo tiene?
List<>
en general, mientras que ese pregunta List<object>
específicamente
Respuestas:
Si, mas o menos. List<T>
Es una clase genérica. Es compatible con el almacenamiento de valores de un tipo específico sin conversión hacia o desde object
(que habría incurrido en gastos generales de boxeo / unboxing cuando T
es un tipo de valor en el ArrayList
caso). ArrayList
simplemente almacena object
referencias. Como una colección genérica, List<T>
implementa la IEnumerable<T>
interfaz genérica y se puede usar fácilmente en LINQ (sin requerir ninguna Cast
oOfType
llamar).
ArrayList
pertenece a los días en que C # no tenía genéricos. Está en desuso a favor de List<T>
. No debe usar un ArrayList
código nuevo que apunte a .NET> = 2.0 a menos que tenga que interactuar con una API antigua que lo usa.
ArrayList
en tiempo de ejecución. Aunque estáticamente, requerirá un yeso con ArrayList
.
Usarlo List<T>
puede evitar errores de transmisión. Es muy útil para evitar un error de transmisión en tiempo de ejecución .
Ejemplo:
Aquí (usando ArrayList
) puede compilar este código, pero verá un error de ejecución más adelante.
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
}
Si lo usa List
, evita estos errores:
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;
}
Referencia: MSDN
Para agregar a los puntos anteriores. El uso ArrayList
en el sistema operativo de 64 bits requiere 2 veces más memoria que el uso en el sistema operativo de 32 bits. Mientras tanto, la lista genérica List<T>
usará mucha poca memoria que laArrayList
.
por ejemplo, si utilizamos una ArrayList
de 19 MB en 32 bits, se necesitarían 39 MB en 64 bits. Pero si tienes una lista genéricaList<int>
de 8 MB en 32 bits, solo necesitaría 8.1 MB en 64 bits, lo que es una gran diferencia del 481% en comparación con ArrayList.
Fuente: ArrayList's vs. Lista genérica para tipos primitivos y 64 bits
Otra diferencia para agregar es con respecto a la sincronización de subprocesos.
ArrayList
proporciona cierta seguridad de subprocesos a través de la propiedad Sincronizada, que devuelve un contenedor seguro para subprocesos alrededor de la colección. El contenedor funciona bloqueando toda la colección en cada operación de agregar o quitar. Por lo tanto, cada subproceso que intenta acceder a la colección debe esperar su turno para tomar el único bloqueo. Esto no es escalable y puede causar una degradación significativa del rendimiento para grandes colecciones.
List<T>
no proporciona ninguna sincronización de subprocesos; el código de usuario debe proporcionar toda la sincronización cuando los elementos se agregan o eliminan en varios subprocesos simultáneamente.
Más información aquí Sincronización de subprocesos en .Net Framework
ArrayList
si se puede evitar, pero esta es una razón tonta. El contenedor es completamente opcional después de todo; Si no necesita bloqueo o si necesita un control más granular, no use el envoltorio.
La respuesta simple es,
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
Lea el documento oficial de Microsoft : https://blogs.msdn.microsoft.com/kcwalina/2005/09/23/system-collections-vs-system-collection-generic-and-system-collections-objectmodel/
Nota : debe conocer los genéricos antes de comprender la diferencia: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
ArrayList
es la recopilación de datos de diferentes tipos, mientras que List<>
es la recopilación de un tipo similar de sus propias dependencias.
ArrayList
no son de tipo seguro, mientras que List<T>
son de tipo seguro. Simple :).
El rendimiento ya se ha mencionado en varias respuestas como un factor diferenciador, pero para abordar el tema " ¿Cuánto más lento es el ArrayList
? "Y" ¿Por qué es más lento en general?", Eche un vistazo a continuación.
Siempre que los tipos de valor se utilizan como elementos, el rendimiento disminuye drásticamente con ArrayList
. Considere el caso de simplemente agregar elementos. Debido a que el boxeo continúa, ya que ArrayList
Add solo toma object
parámetros, el recolector de basura se activa para realizar mucho más trabajo que con List<T>
.
¿Cuánto es la diferencia horaria? Al menos varias veces más lento que con List<T>
. Solo eche un vistazo a lo que sucede con el código que agrega valores de 10 mil int a un ArrayList
vs List<T>
:
Esa es una diferencia de tiempo de ejecución de 5x en la columna 'Media', resaltada en amarillo. Tenga en cuenta también la diferencia en el número de recolecciones de basura realizadas para cada uno, resaltado en rojo (no de GC / 1000 ejecuciones).
El uso de un generador de perfiles para ver lo que sucede rápidamente muestra que la mayor parte del tiempo se gasta haciendo GC , en lugar de agregar elementos. Las barras marrones a continuación representan el bloqueo de la actividad del recolector de basura:
He escrito un análisis detallado de lo que sucede con el ArrayList
escenario anterior aquí https://mihai-albert.com/2019/12/15/boxing-performance-in-c-analysis-and-benchmark/ .
Hallazgos similares se encuentran en "CLR vía C #" de Jeffrey Richter. Del capítulo 12 (Genéricos):
[…] Cuando compilo y ejecuto una versión de lanzamiento (con las optimizaciones activadas) de este programa en mi computadora, obtengo el siguiente resultado.
00: 00: 01.6246959 (GCs = 6) Lista <Int32>
00: 00: 10.8555008 (GCs = 390) ArrayList de Int32
00: 00: 02.5427847 (GCs = 4) Lista <String>
00: 00: 02.7944831 (GCs = 7 ) ArrayList of StringEl resultado aquí muestra que usar el algoritmo genérico List con el tipo Int32 es mucho más rápido que usar el algoritmo ArrayList no genérico con Int32. De hecho, la diferencia es fenomenal: 1.6 segundos versus casi 11 segundos. ¡Eso es ~ 7 veces más rápido ! Además, el uso de un tipo de valor (Int32) con ArrayList hace que se produzcan muchas operaciones de boxeo, lo que resulta en 390 recolecciones de basura. Mientras tanto, el algoritmo List requirió 6 recolecciones de basura.
Creo que las diferencias entre ArrayList
y List<T>
son:
List<T>
, donde T es de tipo valor es más rápido que ArrayList
. Esto se debe a que List<T>
evita el boxing / unboxing (donde T es de tipo valor).ArrayList
usa solo para compatibilidad con versiones anteriores. (No es una diferencia real, pero creo que es una nota importante).ArrayList
continuación,List<T>
ArrayList
Tiene IsSynchronized
propiedad. Por lo tanto, es fácil de crear y usar sincronizado ArrayList
. No encontré IsSynchronized
propiedad para List<T>
. También tenga en cuenta que este tipo de sincronización es relativamente ineficiente, 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
tiene una ArrayList.SyncRoot
propiedad que se puede usar para la sincronización ( msdn ). List<T>
no tiene SyncRoot
propiedad, por lo que en la siguiente construcción debe usar algún objeto si usa List<T>
:
ArrayList myCollection = new ArrayList();
lock(myCollection.SyncRoot) // ofcourse you can use another object for this goal
{
foreach (object item in myCollection)
{
// ...
}
}
Como se menciona en la documentación de .NET Framework
No recomendamos que use la
ArrayList
clase para un nuevo desarrollo. En su lugar, le recomendamos que use laList<T>
clase genérica . LaArrayList
clase está diseñada para contener colecciones heterogéneas de objetos. Sin embargo, no siempre ofrece el mejor rendimiento. En cambio, recomendamos lo siguiente:
- Para una colección heterogénea de objetos, use el tipo
List<Object>
(en C #) oList(Of Object)
(en Visual Basic).- Para una colección homogénea de objetos, use la
List<T>
clase
Consulte también No se deben usar colecciones no genéricas
Usando "Lista" puede evitar errores de transmisión. Es muy útil para evitar un error de transmisión en tiempo de ejecución.
Ejemplo:
Aquí (usando ArrayList) puede compilar este código pero verá un error de ejecución más adelante.
// 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.
}
}
Para mí, todo se trata de conocer sus datos. Si continúo expandiendo mi código sobre la base de la eficiencia, tendría que elegir la opción Lista como una forma de descifrar mis datos sin el paso innecesario de siempre preguntarme acerca de los tipos, especialmente 'Tipos personalizados'. Si la máquina entiende la diferencia y puede determinar en qué tipo de datos estoy tratando realmente, ¿por qué debería interponerme y perder el tiempo pasando por los giros de las determinaciones 'SI ENTONCES?' ¿Mi filosofía es dejar que la máquina funcione para mí en lugar de que yo trabaje en la máquina? Conocer las diferencias únicas de los diferentes comandos de código de objeto ayuda mucho a que su código sea tan eficiente.
Tom Johnson (una entrada ... una salida)