¿Cuál es la diferencia entre List (of T) y Collection (of T)?

Los he visto usar de la misma manera, y me preocupa que vaya por un camino en el diseño que es irreversible si no entiendo esto mejor. Además, estoy usando .NET.

Collection es un contenedor personalizable alrededor de IList . Si bien IList no está sellado, no proporciona ningún punto de personalización. Collection métodos de Collection se delegan por defecto a los métodos estándar de IList , pero se pueden anular fácilmente para hacer lo que se desee. También es posible conectar eventos dentro de una Collection que no creo que se pueda hacer con un IList.

En resumen, es mucho más fácil extenderlo después del hecho, lo que podría significar una refactorización mucho menor.

En C #, hay tres conceptos para representar una bolsa de objetos. Para boost las características, son:

  • Enumerable : desordenado, no modificable
  • Colección : puede agregar / eliminar elementos
  • Lista : permite que los artículos tengan un pedido (accediendo y eliminando por índice)

Enumerable no tiene orden. No puede agregar o eliminar elementos del conjunto. Ni siquiera puede obtener un recuento de los elementos en el conjunto. Le permite acceder estrictamente a cada elemento del conjunto, uno después del otro.

La colección es un conjunto modificable. Puede agregar y eliminar objetos del conjunto, también puede obtener el recuento de elementos en el conjunto. Pero todavía no hay orden, y porque no hay orden: no hay forma de acceder a un elemento por índice, ni existe ninguna forma de ordenar.

La lista es un conjunto ordenado de objetos. Puede ordenar la lista, acceder a los elementos por índice, eliminar elementos por índice.

De hecho, cuando se observan las interfaces para estos, se construyen unos sobre otros:

  • interface IEnumerable

    • GetEnumeration
  • interface ICollection : IEnumerable

    • Add
    • Remove
    • Clear
    • Count
  • interface IList = ICollection

    • Insert
    • IndexOf
    • RemoveAt

Al declarar variables o parámetros de método, debe elegir usar

  • IEnumerable
  • ICollection
  • IList

basado conceptualmente, tienes que ver con el conjunto de objetos.

Si solo necesita poder hacer algo con cada objeto de una lista, solo necesita IEnumerable :

 void SaveEveryUser(IEnumerable users) { for User u in users ... } 

No importa si los Usuarios están guardados en una List , Collection , Array o cualquier otra cosa. Solo necesita la IEnumerable .

Si necesita poder agregar, eliminar o contar los elementos de un conjunto, utilice una Colección :

 ICollection users = new Collection(); users.Add(new User()); 

Si le importa un orden de clasificación y necesita que el pedido sea correcto, utilice una Lista :

 IList users = FetchUsers(db); 

En forma de gráfico:

 | Feature | IEnumerable | ICollection | IList | |------------------------|----------------|----------------|----------| | Enumerating items | X | X | X | | | | | | | Adding items | | X | X | | Removing items | | X | X | | Count of items | | X | X | | | | | | | Accessing by index | | | X | | Removing by indexx | | | X | | Getting index of item | | | X | 

La List y la Collection en System.Collections.Generic son dos clases que implementan estas interfaces; pero no son las únicas clases:

  • ConcurrentBag es una bolsa ordenada de objetos ( IEnumerable )
  • LinkedList es una bolsa donde no tiene permitido acceder a los elementos por índice ( ICollection ); pero puedes agregar y eliminar arbitrariamente elementos de la colección
  • SynchronizedCollection en una colección ordenada, donde puede agregar / eliminar elementos por índice

Para que pueda cambiar fácilmente:

 IEnumerable users = new SynchronizedCollection(); SaveEveryUser(users); 

tl; dr

  • Enumerable : artículos de acceso, desordenados, no modificables
  • Colección – puede ser modificado (agregar, borrar, contar)
  • Lista – puede acceder por índice

Elija el concepto que necesita, luego use la clase correspondiente.

List está destinado para uso interno dentro del código de la aplicación. Debe evitar escribir API públicas que acepten o devuelvan List (considere usar una superclase o una interfaz de colección en su lugar).

Collection sirve una clase base para colecciones personalizadas (aunque se puede usar directamente).

Considere usar Collection en su código a menos que haya características específicas de List que necesite.

Lo anterior son solo recomendaciones.

[Adaptado de: Pautas de diseño del marco, segunda edición]

List es un contenedor muy común, porque es muy versátil (con muchos métodos útiles, como Sort , Find , etc.), pero no tiene puntos de extensión si desea anular el comportamiento (marque los elementos en insertar , por ejemplo).

Collection es un contenedor alrededor de cualquier IList (por defecto a List ) – tiene los puntos de extensión (métodos virtual ), pero no tantos métodos de soporte como Find . Debido a la indirección, es un poco más lento que List , pero no por mucho.

Con LINQ, los métodos adicionales en List vuelven menos importantes, ya que LINQ-to-Objects tiende a proporcionarlos de todos modos … por ejemplo First(pred) , OrderBy(...) , etc.

La lista es más rápida.

Haz por ejemplo

 private void button1_Click(object sender, EventArgs e) { Collection c = new Collection(); Stopwatch s = new Stopwatch(); s.Start(); for (long i = 0; i < = 10000000; i++) { c.Add(i); } s.Stop(); MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString()); List l = new List(); Stopwatch s2 = new Stopwatch(); s2.Start(); for (long i = 0; i < = 10000000; i++) { l.Add(i); } s2.Stop(); MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString()); } 

en mi máquina, la List<> es casi dos veces más rápida.

Editar

No puedo entender por qué las personas están bajando esto. Tanto en mi máquina de trabajo como en mi máquina doméstica, el código List <> es 80% más rápido.

La lista representa una colección donde el orden de los elementos es importante. También es compatible con los métodos sa Ordenar y buscar. La recostackción es una estructura de datos más general que hace menos suposiciones sobre los datos y también admite menos métodos para manipularla. Si desea exponer una estructura de datos personalizada, probablemente debería extender la colección. Si necesita manipular datos sin exponer la estructura de datos, una lista es probablemente la manera más conveniente de hacerlo.

Esta es una de esas preguntas de la escuela de posgrado. Una colección de T es una especie de resumen; puede haber una implementación predeterminada (no soy un tipo .net / c #) pero una colección tendrá operaciones básicas como agregar, eliminar, iterar, etc.

La lista de T implica algunos detalles sobre estas operaciones: agregar debe tomar un tiempo constante, quitar debe tomar un tiempo proporcional a la cantidad de elementos, el primero debe ser consiente. En general, una Lista es un tipo de Colección, pero una Colección no es necesariamente un tipo de Lista.

Hanselman habla : ” Collection parece una lista, e incluso tiene una List internamente. CADA método único delega en la List interna List . Incluye una propiedad protegida que expone la List .”

EDITAR: Collection no existe en System.Generic.Collections .NET 3.5. Si migras de .NET 2.0 a 3.5 necesitarás cambiar algún código si estás utilizando muchos objetos Collection , a menos que me falta algo obvio …

EDIT 2: Collection está ahora en el espacio de nombres System.Collections.ObjectModel en .NET 3.5. El archivo de ayuda dice esto:

“El espacio de nombres System.Collections.ObjectModel contiene clases que se pueden usar como colecciones en el modelo de objetos de una biblioteca reutilizable. Utilice estas clases cuando las propiedades o métodos devuelvan colecciones”.

Todas estas interfaces heredan de IEnumerable , que debe asegurarse de comprender. Esa interfaz básicamente le permite usar la clase en una statement foreach (en C #).

  • ICollection es la más básica de las interfaces que enumeró. Es una interfaz enumerable que admite un Count y eso es todo.
  • IList es todo lo que ICollection es, pero también admite agregar y eliminar elementos, recuperar elementos por índice, etc. Es la interfaz más utilizada para “listas de objetos”, que es vaga, lo sé.
  • IQueryable es una interfaz enumerable que admite LINQ. Siempre puede crear un IQueryable desde un IList y usar LINQ en Objects, pero también encuentra que IQueryable usa para la ejecución diferida de sentencias SQL en LINQ to SQL y LINQ to Entities.
  • IDictionary es un animal diferente en el sentido de que es un mapeo de claves únicas para los valores. También es enumerable en que puede enumerar los pares clave / valor, pero de lo contrario sirve para un propósito diferente al de los otros que enumeró

Según MSDN, List (Of T) .Add es “una operación O (n)” (cuando se excede “Capacidad”) mientras Collection (Of T) .Add siempre es “una operación O (1)”. Eso sería comprensible si la Lista se implementa usando una Matriz y Colección una Lista Vinculada. Sin embargo, si ese fuera el caso, uno esperaría que Collection (Of T) .Item fuera “una operación de O (n)”. Pero … ¡no es así !?! Colección (de T). El elemento es “una operación O (1)” al igual que la Lista (de T). Ítem.

Además de eso, “tuinstoel” ’29 de diciembre ’08 a las 22:31′ ‘publicación anterior muestra que las pruebas de velocidad muestran Lista (De T) .Agregar para ser más rápido que la Colección (De T). Agregar el que he reproducido con Long’s y String’s. Aunque solo obtuve ~ 33% más rápido contra su reclamo del 80%, según MSDN, ¡debería haber sido lo opuesto y por “n” veces!?!

Ambos implementan las mismas interfaces, por lo que se comportarán de la misma manera. Quizás se implementen de manera diferente internamente, pero esto debería ser probado.

Las únicas diferencias reales que veo son los espacios de nombres y el hecho de que Collection está marcado con ComVisibleAttribute(false) , por lo que el código COM no puede usarlo.

Además de otras respuestas, he comstackdo una descripción general rápida de la lista genérica y las capacidades de recostackción. La colección es un subconjunto limitado de la Lista:

 * = presente
 o = parcialmente presente

 Propiedad / Método Colección  Lista 
 ---------------------------------------------- Add() * * AddRange() * AsReadOnly() * BinarySearch() * Capacity * Clear() * * Contains() * * ConvertAll() * CopyTo() o * Count * * Equals() * * Exists() * Find() * FindAll() * FindIndex() * FindLast() * FindLastIndex() * ForEach() * GetEnumerator() * * GetHashCode() * * GetRange() * GetType() * * IndexOf() o * Insert() * * InsertRange() * Item() * * LastIndexOf() * New() o * ReferenceEquals() * * Remove() * * RemoveAll() * RemoveAt() * * RemoveRange() * Reverse() * Sort() * ToArray() * ToString() * * TrimExcess() * TrueForAll() *