6

Hace poco respondi la pregunta de ¿Cómo agregar elementos a un array en C#? y mientas proponia la solución alternativa que era usar la clase List, me recorde que tambien hay una clase llamada ArrayList.

Al comparar la documentación de ArrayList y List, en algunas partes de estos articulos dice:

"La clase ArrayList esta diseñada para retener colecciones heterogeneas de objetos. Sin embargo, no siempre ofrece el mejor rendimiento."

Y tambien

"La clase List se ejecuta mejor en la mayoria de casos y es de tipado seguro."

Después el articulo de List trata de explicar porqué List tiene un mejor rendimiento, pero esta es la parte que no entiendo. Dice literalmente:

"For a List, if a value type is used for type T, the compiler generates an implementation of the List class specifically for that value type. That means a list element of a List object does not have to be boxed before the element can be used."

"Para una List, si un tipo es usado para el tipo en la lista, el compilador genera una implementación de la clase List especificamente para ese valor de tipo. Eso significa que un elemento listado del objeto List no tiene que estar encajonado antes de poder ser usado."

*Traducción libre de mi parte

¿Cúal es realmente la diferencia entre ArrayList y List y por qué dice que List tiene un mejor rendimiento?


P.D.: +10 brownie points al que me diga que debo entender por "boxed" en ese parrafo, que la verdad no pude traducirlo muy bien. Edit: Flxtr se ha llevado los brownie points.

Carlos Muñoz
  • 12,864
  • 2
  • 42
  • 62
Kenny Barrera
  • 2,075
  • 3
  • 22
  • 38
  • 2
    *Boxed* se refiere a que antes de que el valor sea guardado en memoria, se le aplica el término "*boxing*", lo cual es el casteo a un `object`, y se aplica "*unboxing*" para poder leer el valor, es decir, de `object` al tipo de dato con el que está referenciado. Talvés una posible traducción sería "encajonado". – Phi Aug 28 '17 at 21:47
  • ¿Porqué solo para C#?, no sería mejor generalizar y decir para `.net`. – Davlio Aug 28 '17 at 22:09
  • @Davlio pues no lo habia pensado, pero si, supongo que para terminos de calidad del sitio y futuros usuarios seria mejor. Lo editare. – Kenny Barrera Aug 28 '17 at 22:11
  • Me ganaron los brownie points :P – Carlos Muñoz Aug 28 '17 at 22:11
  • 2
    Ok entonces también generalizaré la respuesta para .NET en general – Carlos Muñoz Aug 28 '17 at 22:12

4 Answers4

13

ArrayList es una clase que fue creada desde la versión 1 de C# y el .NET Framework antes que se agregen Generics, mientras que List<T> es la clase que la ha reemplazado desde C# 2, .NET Framework 2.0 y VB.NET 2008 (8.0) en adelante.

La diferencia principal es que una instancia de ArrayList permite que se agreguen diversos tipos a la colección.

Ejemplo:

C#

var arrayList = new ArrayList();
arrayList.Add(1); // Puede contener enteros
arrayList.Add("Dos"); // Tambien strings
arrayList.Add(false); // y booleans, etc

VB

Dim arrayList As New ArrayList()
arrayList.Add(1) ' Puede contener enteros
arrayList.Add("Dos") ' Tambien strings
arrayList.Add(False) ' y booleans, etc

Mientras que List<T> necesita que se defina el tipo de los elementos de la lista al ser instanciado

C#

var list = new List<int>();
list.Add(1);  // permite agregar enteros
list.Add("Dos"); // error de sintaxis, solo se pueden agregar enteros

VB

Dim list As New List(Of Integer)
list.Add(1) ' permite agregar enteros
list.Add("Dos") ' error de sintaxis, solo se pueden agregar enteros

Y acerca del rendimiento la difierencia está en los términos boxing y unboxing

Boxing se refiere al hecho de envolver un valor de tipo Reference type (como int, char, float, double, ... entre otros) dentro de una referencia si es que se quiere asignar a una variable o parámetro de tipo object. Unboxing se refiere al proceso inverso, es decir a obtener al valor del objeto en una variable de tipo reference type.

El problema se encuentra que este proceso de boxing y unboxing ocurre en el caso de ArrayList cuando se agrega o obtiene un valor.

Ejemplos:

C#

var arrayList = new ArrayList();
arrayList.Add(1); // Boxing. Ya que el método Add espera un object
var numero = (int)arrayList[0]; // Unboxing. El indexer devuelve un object que debe ser casteado a `int`

VB

Dim arrayList As New ArrayList()
arrayList.Add(1) ' Boxing. Ya que el método Add espera un object
Dim numero As Integer = arrayList(0) ' Unboxing. El indexer devuelve un object que debe ser casteado a `int`

Este proceso toma tiempo de ejecución por lo que es mas lento que el caso genérico.

En el caso genérico con List<T> este proceso es inexistente ya que el compilador genera el código para los tipos de datos exactos, (en este caso int) y no requiere ningún tiop de conversión.

C#

var list = new List<int>;
list.Add(1); // No hay boxing puesto que el método espera un int
var numero = list[0]; // No hay cast ni unboxing puesto que el indexer devuelve un int

VB

Dim list As New List(Of Integer)
list.Add(1) ' No hay boxing puesto que el método espera un int
Dim numero As Integer = list(0) ' No hay cast ni unboxing puesto que el indexer devuelve un int

Te recomiendo que siempre utilices List<T> la verdad no conozco un caso donde convenga usar ArrayList ya que si bien no ha sido marcado como obsoleto, en la práctica ya no se usa.

Carlos Muñoz
  • 12,864
  • 2
  • 42
  • 62
2

Básicamente, ArrayList necesita realizar boxing y unboxing cada vez que se guarda/accede a un elemento del array. Esto es así debido a que ArrayList guarda referencias a objetos de tipo object, por tanto necesita realizar la tarea de cast contínuamente.

Por otra parte, List no necesita realizar esa tarea, pues el compilador implementa una lista concreta (¿especializada?) para el tipo T a trabajar. Por eso mismo también es más segura (aunque tampoco asegura la ordenación ojo).

lmfresneda
  • 478
  • 3
  • 10
1

La diferencia se podría entender así:

  • Al declarar List le asignas un tipo (String, integer, Booleano) y a medida que agregas elementos es un proceso de asignación de valores de un tipo en específico a un sector de memoria.

  • ArrayList en cambio convierte la información que recibe en un objeto completamente nuevo antes de asignarle un espacio en memoria (boxing) y así por cada item del arrayList. Al leerlo no solo debes obtenerlo desde el espacio en RAM, sino que también debe "crearlo" y todas sus propiedades. Lo que consume muchisimos recursos

Tridam
  • 386
  • 1
  • 9
0

La clase List(Of T) -T hace referencia a Type (un tipo fijo)- es muy potente. Una de sus mayores cualidades es implementar el interface IEnumerable(Of T), lo que permite el acceso a muchos métodos. Un objeto de esta clase puede ser transformado con facilidad en una array utilizando el método ToArray. Podemos leer la documentación de MSDN sobre esta clase en: List(Of T) en MSDN

Una importante ventaja de List(Of T) es que los objetos de esta clase pueden formar parte de consultas en lenguaje LINQ permitiéndonos transformar listas de objetos de un tipo en listas de objetos de otro tipo o en un objeto estadístico como el primer elemento de una lista, el último, el máximo, el mínimo... LINQ