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 Tes un tipo de valor en el ArrayListcaso). ArrayListsimplemente almacena objectreferencias. 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 CastoOfType llamar).
ArrayListpertenece a los días en que C # no tenía genéricos. Está en desuso a favor de List<T>. No debe usar un ArrayListcódigo nuevo que apunte a .NET> = 2.0 a menos que tenga que interactuar con una API antigua que lo usa.
¿Te importaría explicar por qué usaste "boxeo" y no "casting"? ¿Qué boxeo pasa aquí? ¿Los objetos están asignados / desasigados?
Benjamin Gruenbaum
2
@BenjaminGruenbaum Tienes razón en que el casting sería más general. Dicho esto, la verdadera diferencia en tiempo de ejecución es cuando se trata de tipos de valores (que es lo que asumí cuando escribí "boxeo"). Para los tipos de referencia, el comportamiento es efectivamente el mismo que ArrayListen tiempo de ejecución. Aunque estáticamente, requerirá un yeso con ArrayList.
Mehrdad Afshari
Me preguntaba si el framework debería restringir que T sea del tipo "objeto", ya que ArrayList lo permite implícitamente.
@ Ant_222, ese blog fue escrito hace casi 15 años. Creo que la evidencia de la última década ha demostrado que los genéricos no son dañinos. :)
Scott Adams
101
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 =newArrayList();
array1.Add(1);
array1.Add("Pony");//No error at compile processint total =0;foreach(int num in array1){
total += num;//-->Runtime Error}
Si lo usa List, evita estos errores:
List<int> list1 =newList<int>();
list1.Add(1);//list1.Add("Pony"); //<-- Error at compile processint total =0;foreach(int num in list1 ){
total += num;}
Puede verificar el tipo cuando extrae de ArrayList para evitar errores de conversión. Hoy en día las personas usan objetos, haciendo que ArrayList ya no sea necesario.
Cambiar el
1
i +1 a la justificación, pero aún puede hacerlo si (num es int) {} a su lista de matriz para evitar errores
Mina Gabriel
Prevenir errores de fundición y gastos generales de boxeo. Más o menos las razones de los genéricos en general.
marsze
26
Para agregar a los puntos anteriores. El uso ArrayListen 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 ArrayListde 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.
eso solo es cierto para almacenar tipos de valor, no tipos de referencia. La diferencia se debe al hecho de que una lista de arrays solo puede contener punteros, y los datos en sí mismos deben almacenarse en otro lugar. Por otro lado, los tipos de valores se pueden almacenar directamente en una lista.
Rasmus Damgaard Nielsen
19
Otra diferencia para agregar es con respecto a la sincronización de subprocesos.
ArrayListproporciona 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.
No digo que debas usarlo ArrayListsi 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.
Thorarin
1
Si desea seguridad de subprocesos, le sugiero que consulte el espacio de nombres System.Collections.Concurrent antes de considerar ArrayList.
Ykok
15
La respuesta simple es,
ArrayList es no genérico
Es un tipo de objeto, por lo que puede almacenar cualquier tipo de datos en él.
Puede almacenar cualquier valor (tipo de valor o tipo de referencia) como string, int, employee y object en ArrayList. (Nota y)
Boxing y Unboxing sucederán.
No es seguro.
Es mayor
La lista es genérica
Es un tipo de tipo, por lo que puede especificar la T en tiempo de ejecución.
Puede almacenar un único valor de Tipo T (cadena o int o empleado u objeto) según la declaración. (Nota o)
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 ArrayListAdd solo toma objectpará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 ArrayListvs 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:
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 String
El 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 ArrayListy 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).
Muchas fuentes dicen que generalmente se ArrayListusa solo para compatibilidad con versiones anteriores. (No es una diferencia real, pero creo que es una nota importante).
La reflexión es más fácil con no genérico ArrayListcontinuación,List<T>
ArrayListTiene IsSynchronizedpropiedad. Por lo tanto, es fácil de crear y usar sincronizado ArrayList. No encontré IsSynchronizedpropiedad para List<T>. También tenga en cuenta que este tipo de sincronización es relativamente ineficiente, msdn ):
var arraylist =newArrayList();var arrayListSyncronized =ArrayList.Synchronized(arraylist
Console.WriteLine($"syncronized {arraylist.IsSynchronized}");Console.WriteLine($"syncronized {arrayListSyncronized.IsSynchronized}");varlist=newList<object>();var listSyncronized =ArrayList.Synchronized(list);Console.WriteLine($"syncronized {list.IsSynchronized}");//error, no such propConsole.WriteLine($"syncronized {list.IsSynchronized}");//error, no such prop
ArrayListtiene una ArrayList.SyncRootpropiedad que se puede usar para la sincronización ( msdn ). List<T>no tiene SyncRootpropiedad, por lo que en la siguiente construcción debe usar algún objeto si usa List<T>:
ArrayList myCollection =newArrayList();lock(myCollection.SyncRoot)// ofcourse you can use another object for this goal{foreach(object item in myCollection){// ...}}
No recomendamos que use la ArrayListclase para un nuevo desarrollo. En su lugar, le recomendamos que use la List<T>
clase genérica . La ArrayListclase 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 #) o List(Of Object)(en Visual Basic).
Para una colección homogénea de objetos, use la List<T>clase
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 ArrayListSystem.Collections.ArrayList mixedList =newSystem.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 =newSystem.Collections.ArrayList();System.Collections.ArrayList strList =newSystem.Collections.ArrayList();foreach(object obj in mixedList){if(obj.GetType().Equals(typeof(int))){
intList.Add(obj);}elseif(obj.GetType().Equals(typeof(string))){
strList.Add(obj);}else{// error.}}
¿Qué agrega esto más allá de la respuesta que las termas dieron tres años antes? Tiene casi el mismo texto textualmente, sin vincular a la fuente, sin formatear correctamente, etc.
Douglas Zare
-3
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.
List<>
en general, mientras que ese preguntaList<object>
específicamenteRespuestas:
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 desdeobject
(que habría incurrido en gastos generales de boxeo / unboxing cuandoT
es un tipo de valor en elArrayList
caso).ArrayList
simplemente almacenaobject
referencias. Como una colección genérica,List<T>
implementa laIEnumerable<T>
interfaz genérica y se puede usar fácilmente en LINQ (sin requerir ningunaCast
oOfType
llamar).ArrayList
pertenece a los días en que C # no tenía genéricos. Está en desuso a favor deList<T>
. No debe usar unArrayList
código nuevo que apunte a .NET> = 2.0 a menos que tenga que interactuar con una API antigua que lo usa.fuente
ArrayList
en tiempo de ejecución. Aunque estáticamente, requerirá un yeso conArrayList
.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.Si lo usa
List
, evita estos errores:Referencia: MSDN
fuente
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éricaList<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
fuente
Otra diferencia para agregar es con respecto a la sincronización de subprocesos.
Más información aquí Sincronización de subprocesos en .Net Framework
fuente
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 es no genérico
La lista es genérica
Ejemplo:
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/
fuente
ArrayList
es la recopilación de datos de diferentes tipos, mientras queList<>
es la recopilación de un tipo similar de sus propias dependencias.fuente
ArrayList
no son de tipo seguro, mientras queList<T>
son de tipo seguro. Simple :).fuente
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 queArrayList
Add solo tomaobject
parámetros, el recolector de basura se activa para realizar mucho más trabajo que conList<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 unArrayList
vsList<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):
fuente
Creo que las diferencias entre
ArrayList
yList<T>
son:List<T>
, donde T es de tipo valor es más rápido queArrayList
. Esto se debe a queList<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
TieneIsSynchronized
propiedad. Por lo tanto, es fácil de crear y usar sincronizadoArrayList
. No encontréIsSynchronized
propiedad paraList<T>
. También tenga en cuenta que este tipo de sincronización es relativamente ineficiente, msdn ):ArrayList
tiene unaArrayList.SyncRoot
propiedad que se puede usar para la sincronización ( msdn ).List<T>
no tieneSyncRoot
propiedad, por lo que en la siguiente construcción debe usar algún objeto si usaList<T>
:fuente
Como se menciona en la documentación de .NET Framework
Consulte también No se deben usar colecciones no genéricas
fuente
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.
fuente
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)
fuente