vacia tipos metodos listas lista genericas dinamica colecciones c# .net memory-management collections object-initializers

c# - metodos - Capacidad inicial de los tipos de colección, p. Ej. Diccionario, Lista



public list c# (4)

Ciertos tipos de colección en .Net tienen un parámetro de constructor de "capacidad inicial" opcional. Por ejemplo:

Dictionary<string, string> something = new Dictionary<string,string>(20); List<string> anything = new List<string>(50);

Parece que no puedo encontrar cuál es la capacidad inicial predeterminada para estos objetos en MSDN.

Si sé que solo almacenaré 12 o más elementos en un diccionario, ¿no tiene sentido establecer la capacidad inicial en algo así como 20?

Mi razonamiento es que, suponiendo que la capacidad crezca como lo hace para un StringBuilder, que se duplica cada vez que se golpea la capacidad, y cada reasignación es costosa, ¿por qué no preestablecer el tamaño a algo que usted sabe que almacenará sus datos, con algún habitación por si acaso? Si la capacidad inicial es 100, y sé que solo necesitaré una docena más o menos, parece que el resto de esa memoria está asignada para nada.


Al verificar la fuente, la capacidad predeterminada para List<T> y Dictionary<TKey, TValue> es 0.


Otro problema con el ConcurrentDictionary (actualmente) y el uso de su constructor para establecer un tamaño inicial es que su rendimiento parece estar obstaculizado.

Por ejemplo, aquí hay algunos códigos de ejemplo y puntos de referencia que probé.

Ejecuté el código en mi máquina y obtuve resultados similares.

Es decir, cuando se especifica el tamaño inicial, no hace nada para aumentar la velocidad de ConcurrentDictionary al agregar objetos. Técnicamente, creo que debería hacerlo porque no tiene que tomar tiempo ni recursos para redimensionarse.

Sí, puede que no funcione tan rápido como un diccionario normal, pero aún esperaría que un ConcurrentDictionary con su tamaño inicial establecido tenga un rendimiento consistente y más rápido que un ConcurrentDictionary que no tenga su tamaño inicial establecido, especialmente cuando uno sabe de antemano la cantidad de elementos que se le agregarán.

Entonces, la moraleja de la historia es establecer el tamaño inicial que no siempre garantiza una mejora en el rendimiento.


Si conoces el tamaño, cuéntalo; una optimización menor en la mayoría de los casos "pequeños", pero útil para colecciones más grandes. Prefiero preocuparme por esto principalmente si arrojo una cantidad "decente" de datos, ya que puede evitar tener que asignar, copiar y recopilar varias matrices.

La mayoría de las colecciones usan una estrategia de duplicación.


Si los valores predeterminados no están documentados, es probable que la capacidad inicial óptima sea un detalle de la implementación y esté sujeta a cambios entre las versiones del marco. Es decir, no debe escribir código que asuma un cierto valor predeterminado.

Las sobrecargas de constructor con una capacidad son para casos en los que usted sabe mejor que la clase qué cantidad de elementos debe esperarse. Por ejemplo, si crea una colección de 50 valores y sabe que este número nunca aumentará, puede inicializar la colección con una capacidad de 50, por lo que no tendrá que cambiar el tamaño si la capacidad predeterminada es menor.

Dicho esto, puede determinar los valores predeterminados utilizando Reflector. Por ejemplo, en .NET 4.0 (y probablemente también en versiones anteriores),

  • una Lista <T> se inicializa con una capacidad de 0. Cuando se agrega el primer elemento, se reinicializa a una capacidad de 4. Posteriormente, cada vez que se alcanza la capacidad, la capacidad se duplica.

  • un diccionario <T> está inicializado con una capacidad de 0 también. Pero usa un algoritmo completamente diferente para aumentar la capacidad: aumenta la capacidad siempre para los números primos.