Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
A menudo, los datos similares se pueden controlar de forma más eficaz cuando se almacenan y manipulan como una colección. Puede usar la clase System.Array o las clases en los espacios de nombres System.Collections, System.Collections.Generic, System.Collections.Concurrent y System.Collections.Immutable para agregar, quitar y modificar elementos individuales o un intervalo de elementos de una colección.
Hay dos tipos principales de colecciones; colecciones genéricas y colecciones no genéricas. Las colecciones genéricas son de seguridad de tipos en tiempo de compilación. Por este motivo, las colecciones genéricas suelen ofrecer un mejor rendimiento. Las colecciones genéricas aceptan un parámetro de tipo cuando se construyen. No requieren que se convierta con origen y destino el tipo Object al agregar o quitar elementos de la colección. Además, la mayoría de las colecciones genéricas se admiten en aplicaciones de la Tienda Windows. Las colecciones no genéricas almacenan elementos como Object, requieren una conversión y la mayoría de ellas no son compatibles con el desarrollo de aplicaciones de la Tienda Windows. Sin embargo, puede que vea colecciones no genéricas en código antiguo.
En .NET Framework 4 y versiones posteriores, las colecciones del espacio de nombres System.Collections.Concurrent proporcionan operaciones eficientes y seguras para acceder a elementos de colección desde múltiples subprocesos. Las clases de colección inmutables en el espacio de nombres System.Collections.Immutable (paquete de NuGet) son intrínsecamente seguras para los subprocesos, ya que las operaciones se realizan en una copia de la colección original, mientras que la colección original no se puede modificar.
Características comunes de la colección
Todas las colecciones proporcionan métodos para agregar, quitar o buscar elementos en la colección. Además, todas las colecciones que implementan directa o indirectamente la ICollection interfaz o la ICollection<T> interfaz comparten estas características:
La capacidad de enumerar la colección
Las colecciones de .NET implementan System.Collections.IEnumerable o System.Collections.Generic.IEnumerable<T> para permitir que la colección sea recorrida. Un enumerador se puede considerar como un puntero móvil a cualquier elemento de la colección. Las instrucciones foreach, in y For Each...Next usan el enumerador expuesto por el método GetEnumerator y ocultan la complejidad que supone manipular el enumerador. Además, cualquier colección que implemente System.Collections.Generic.IEnumerable<T> se considera un tipo consultable y se puede consultar con LINQ. Las consultas LINQ proporcionan un patrón común para acceder a los datos. Normalmente son más concisos y legibles que los bucles estándar
foreach
y proporcionan funcionalidades de filtrado, ordenación y agrupación. Las consultas LINQ también pueden mejorar el rendimiento. Para obtener más información, vea LINQ to Objects (C#), LINQ to Objects (Visual Basic), Parallel LINQ (PLINQ), Introduction to LINQ Queries (C#) y Basic Query Operations (Visual Basic).La capacidad de copiar el contenido de la colección en una matriz
Todas las colecciones se pueden copiar en una matriz mediante el
CopyTo
método . Sin embargo, el orden de los elementos de la nueva matriz se basa en la secuencia en la que el enumerador los devuelve. La matriz resultante siempre es unidimensional con un límite inferior de cero.
Además, muchas clases de colección contienen las siguientes características:
Propiedades de capacidad y recuento
La capacidad de una colección es el número de elementos que puede contener. El recuento de una colección es el número de elementos que contiene realmente. Algunas colecciones ocultan la capacidad, el recuento, o ambos.
La mayoría de las colecciones se expanden automáticamente en capacidad cuando se alcanza la capacidad actual. La memoria se reasigna y los elementos se copian de la colección antigua a la nueva. Este diseño reduce el código necesario para usar la colección. Sin embargo, el rendimiento de la colección podría verse afectado negativamente. Por ejemplo, para List<T>, si Count es menor que Capacity, agregar un elemento es una operación de O(1). Si es necesario aumentar la capacidad para acomodar el nuevo elemento, agregar un elemento se convierte en una operación O(
n
), donden
es Count. La mejor manera de evitar un rendimiento deficiente causado por varias reasignaciones es establecer la capacidad inicial para que sea el tamaño estimado de la colección.Un BitArray es un caso especial; su capacidad es la misma que su longitud, que es la misma que su recuento.
Límite inferior coherente
El límite inferior de una colección es el índice de su primer elemento. Todas las colecciones indizadas en el espacio de nombres System.Collections tienen un límite inferior de cero, lo que significa que están indizadas en 0. Array tiene un límite inferior de cero de forma predeterminada, pero se puede definir un límite inferior diferente al crear una instancia de la clase Array mediante Array.CreateInstance.
Sincronización para el acceso de varios subprocesos (solo clases System.Collections).
Los tipos de colecciones no genéricas del espacio de nombres System.Collections proporcionan una seguridad de subprocesos con sincronización; normalmente se exponen a través de los miembros SyncRoot y IsSynchronized. Estas colecciones no son seguras para subprocesos de forma predeterminada. Si necesita acceso multiproceso escalable y eficaz a una colección, use una de las clases del System.Collections.Concurrent espacio de nombres o considere la posibilidad de usar una colección inmutable. Para obtener más información, consulte Thread-Safe Colecciones.
Elección de una colección
En general, debería utilizar colecciones genéricas. En la tabla siguiente se describen algunos escenarios de colección comunes y las clases de colección que puede usar para esos escenarios. Si no está familiarizado con las colecciones genéricas, la tabla siguiente le ayudará a elegir la colección genérica que mejor funcione para la tarea:
Quiero... | Opciones de colección genérica | Opciones de colección no genéricas | Opciones de colección de subprocesos o inmutable |
---|---|---|---|
Almacenar elementos como pares clave-valor para una búsqueda rápida por clave | Dictionary<TKey,TValue> | Hashtable (Colección de pares clave-valor organizados en función del código hash de la clave). |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
Acceso a elementos por índice | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
Utilizar elementos FIFO (el primero en entrar es el primero en salir) | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
Utilizar datos LIFO (el último en entrar es el primero en salir) | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
Obtener acceso a elementos secuencialmente | LinkedList<T> | Sin recomendación | Sin recomendación |
Recibir notificaciones cuando se quitan o agregan elementos a la colección. (implementa INotifyPropertyChanged y INotifyCollectionChanged) | ObservableCollection<T> | Sin recomendación | Sin recomendación |
Una colección ordenada | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
Un conjunto para funciones matemáticas | HashSet<T> SortedSet<T> |
Sin recomendación | ImmutableHashSet<T> ImmutableSortedSet<T> |
Complejidad algorítmica de colecciones
Al elegir una clase de colección, es importante considerar posibles compensaciones en el rendimiento. Use la tabla siguiente para hacer referencia a cómo se comparan varios tipos de colección mutables en complejidad algorítmica con sus equivalentes inmutables correspondientes. A menudo, los tipos de colección inmutables son menos eficaces, pero proporcionan inmutabilidad, lo que suele ser una ventaja comparativa válida.
Cambiable | Amortizado | Peor caso | Inmutable | Complejidad |
---|---|---|---|---|
Stack<T>.Push |
O(1) | O(n ) |
ImmutableStack<T>.Push |
O(1) |
Queue<T>.Enqueue |
O(1) | O(n ) |
ImmutableQueue<T>.Enqueue |
O(1) |
List<T>.Add |
O(1) | O(n ) |
ImmutableList<T>.Add |
O(log n ) |
List<T>.Item[Int32] |
O(1) | O(1) | ImmutableList<T>.Item[Int32] |
O(log n ) |
List<T>.Enumerator |
O(n ) |
O(n ) |
ImmutableList<T>.Enumerator |
O(n ) |
HashSet<T>.Add , búsqueda |
O(1) | O(n ) |
ImmutableHashSet<T>.Add |
O(log n ) |
SortedSet<T>.Add |
O(log n ) |
O(n ) |
ImmutableSortedSet<T>.Add |
O(log n ) |
Dictionary<T>.Add |
O(1) | O(n ) |
ImmutableDictionary<T>.Add |
O(log n ) |
Búsqueda de Dictionary<T> |
O(1) | O(1) – o estrictamente O(n ) |
Búsqueda de ImmutableDictionary<T> |
O(log n ) |
SortedDictionary<T>.Add |
O(log n ) |
O(n log n ) |
ImmutableSortedDictionary<T>.Add |
O(log n ) |
Una List<T>
se puede enumerar de forma eficaz mediante un bucle for
o un bucle foreach
. Un ImmutableList<T>
, sin embargo, realiza un trabajo deficiente dentro de un bucle for
, debido al tiempo de O(log n
) para su indexador. Enumerar un ImmutableList<T>
usando un bucle foreach
es eficaz porque ImmutableList<T>
usa un árbol binario para almacenar sus datos en lugar de una matriz como List<T>
usa. Una matriz se puede indexar rápidamente en, mientras que un árbol binario se debe recorrer hasta que se encuentre el nodo con el índice deseado.
Además, SortedSet<T>
tiene la misma complejidad que ImmutableSortedSet<T>
porque ambos usan árboles binarios. La diferencia significativa es que ImmutableSortedSet<T>
usa un árbol binario inmutable. Ya que ImmutableSortedSet<T>
también ofrece una System.Collections.Immutable.ImmutableSortedSet<T>.Builder clase que permite la mutación, puede tener tanto inmutabilidad como rendimiento.
Artículos relacionados
Título | Descripción |
---|---|
Seleccionar una clase de colección | Describe las distintas colecciones y le ayuda a seleccionar una para su escenario. |
Tipos de colección usados habitualmente | Describe los tipos de colección genéricos y no genéricos usados habitualmente, como System.Array, System.Collections.Generic.List<T>y System.Collections.Generic.Dictionary<TKey,TValue>. |
Cuándo usar colecciones genéricas | Describe el uso de tipos de colección genéricos. |
Comparaciones y ordenaciones dentro de colecciones | Describe el uso de comparaciones de igualdad y comparaciones de ordenación en colecciones. |
Tipos de colección ordenados | Describe el rendimiento y las características de las colecciones ordenadas. |
Tipos de las colecciones Hashtable y Dictionary | Describe las características de los tipos de diccionario genéricos y no genéricos basados en hash. |
Colecciones deThread-Safe | Describe los tipos de colección, como System.Collections.Concurrent.BlockingCollection<T> y System.Collections.Concurrent.ConcurrentBag<T> que admiten el acceso simultáneo seguro y eficaz desde varios subprocesos. |
System.Collections.Immutable | Presenta las colecciones inmutables y proporciona vínculos a los tipos de colección. |