.net - array - ¿Cuál es la diferencia entre List(of T) y Collection(of T)?
return list c# (12)
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.
Además de otras respuestas, he compilado una descripción general rápida de la lista genérica y las capacidades de recopilación. La colección es un subconjunto limitado de la Lista:
* = present
o = partially present
Property/Method Collection<T> List<T>
----------------------------------------------
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() *
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<T>
está marcado con ComVisibleAttribute(false)
, por lo que el código COM no puede usarlo.
En C #, hay tres conceptos para representar una bolsa de objetos. Para aumentar 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<T>
-
GetEnumeration<T>
-
interface ICollection<T> : IEnumerable<T>
-
Add
-
Remove
-
Clear
-
Count
-
interface IList<T> = ICollection<T>
-
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<User> users)
{
for User u in users
...
}
No importa si los Usuarios están guardados en una List<T>
, Collection<T>
, Array<T>
o cualquier otra cosa. Solo necesita la IEnumerable<T>
.
Si necesita poder agregar, eliminar o contar los elementos de un conjunto, utilice una Colección :
ICollection<User> users = new Collection<User>();
users.Add(new User());
Si le importa un orden de clasificación y necesita que el pedido sea correcto, utilice una Lista :
IList<User> users = FetchUsers(db);
En forma de gráfico:
| Feature | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| 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<T>
y la Collection<T>
en System.Collections.Generic
son dos clases que implementan estas interfaces; pero no son las únicas clases:
-
ConcurrentBag<T>
es una bolsa ordenada de objetos (IEnumerable<T>
) -
LinkedList<T>
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<T>
en una colección ordenada, donde puede agregar / eliminar elementos por índice
Para que pueda cambiar fácilmente:
IEnumerable<User> users = new SynchronizedCollection<User>();
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.
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.
La lista es más rápida.
Haz por ejemplo
private void button1_Click(object sender, EventArgs e)
{
Collection<long> c = new Collection<long>();
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<long> l = new List<long>();
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 recopilació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.
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!?!
Todas estas interfaces heredan de IEnumerable
, que debe asegurarse de comprender. Esa interfaz básicamente le permite usar la clase en una declaración foreach (en C #).
-
ICollection
es la más básica de las interfaces que enumeró. Es una interfaz enumerable que admite unCount
y eso es todo. -
IList
es todo lo queICollection
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 unIQueryable
desde un IList y usar LINQ en Objects, pero también encuentra queIQueryable
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ó
Hanselman habla : " Collection<T>
parece una lista, e incluso tiene una List<T>
internamente. CADA método único delega en la List<T>
interna List<T>
. Incluye una propiedad protegida que expone la List<T>
."
EDITAR: Collection<T>
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<T>
, a menos que me falta algo obvio ...
EDIT 2: Collection<T>
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".
Collection<T>
es un contenedor personalizable alrededor de IList<T>
. Si bien IList<T>
no está sellado, no proporciona ningún punto de personalización. Collection<T>
métodos de Collection<T>
se delegan por defecto a los métodos estándar de IList<T>
, pero se pueden anular fácilmente para hacer lo que se desee. También es posible conectar eventos dentro de una Collection<T>
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.
List<T>
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<T>
es un contenedor alrededor de cualquier IList<T>
(por defecto a List<T>
) - 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<T>
, pero no por mucho.
Con LINQ, los métodos adicionales en List<T>
vuelven menos importantes, ya que LINQ-to-Objects tiende a proporcionarlos de todos modos ... por ejemplo First(pred)
, OrderBy(...)
, etc.
List<T>
está destinado para uso interno dentro del código de la aplicación. Debe evitar escribir API públicas que acepten o devuelvan List<T>
(considere usar una superclase o una interfaz de colección en su lugar).
Collection<T>
sirve una clase base para colecciones personalizadas (aunque se puede usar directamente).
Considere usar Collection<T>
en su código a menos que haya características específicas de List<T>
que necesite.
Lo anterior son solo recomendaciones.
[Adaptado de: Pautas de diseño del marco, segunda edición]