2010-05-14 25 views
8

A menudo me encuentro en una situación en la que necesito realizar una operación en un conjunto de propiedades. La operación puede ser cualquier cosa, desde verificar si una propiedad en particular coincide con algo en el conjunto hasta una única iteración de acciones. A veces, el conjunto se genera dinámicamente cuando se llama a la función, algunos se crean con una simple declaración LINQ, otras veces es un conjunto codificado que siempre permanecerá igual. Pero siempre existe una constante: , el conjunto solo existe para una sola operación y no tiene uso antes o después de él.¿Qué contenedor de C# es más eficiente en cuanto a los recursos para una sola operación?

Mi problema es que tengo tantos puntos en mi aplicación donde esto es necesario, pero parece que soy muy, muy inconsistente en la forma de almacenar estos conjuntos. Algunos de ellos son matrices, otros son listas, y justo ahora he encontrado un par de listas vinculadas. Ahora bien, ninguna de las operaciones que me preocupan específicamente debe tener en cuenta los índices, el tamaño del contenedor, el orden o cualquier otra funcionalidad otorgada por cualquiera de los tipos de contenedores individuales. Elegí la eficiencia de recursos porque es una mejor idea que lanzar monedas. Pensé que, dado que el tamaño de la matriz está configurado y es un contenedor muy elemental, esa podría ser mi mejor opción, pero creo que es una mejor idea para preguntar. Alternativamente, si hay una mejor opción no por falta de recursos, sino estrictamente como una mejor opción para este tipo de situación, también sería bueno.

+5

Creo que no debe preocuparse demasiado por la eficiencia de los recursos a menos que los perfiles muestren que hay un problema. Sin embargo, desde la perspectiva de si existe una "verdadera forma" de tratar con esto, esta sigue siendo una pregunta válida. – Joey

+0

No estoy particularmente preocupado por la eficiencia de los recursos, lo elegí como la métrica ya que realmente necesito un motivo más allá de la elección aleatoria. Sin embargo, podría reestructurar la pregunta para simplemente "La mejor opción en general". –

+0

Como compañero programador pedante, entiendo totalmente sus preocupaciones, aunque, como dijo Rössel, probablemente no sea tan importante. Nunca lo perfilé, ya que el problema de rendimiento nunca se me ocurrió, pero personalmente utilizo una matriz para contenido estático y una lista si tengo que crear una lista a partir de otra cosa. – Coincoin

Respuesta

6

Con su reconocimiento de que se trata más de consistencia de codificación que de rendimiento o eficiencia, creo que la práctica general es usar List<T>. Su almacén de respaldo real es una matriz, por lo que realmente no está perdiendo mucho (si es que notifica) a la sobrecarga del contenedor. Sin más calificaciones, no estoy seguro de poder ofrecer nada más que eso.

Por supuesto, si realmente no te importan las cosas que enumeras en tu pregunta, simplemente escribe tus variables como IEnumerable<T> y solo estás tratando con el contenedor real cuando lo estás poblando; donde lo consumas será completamente consistente.

+0

Discutiría por arreglos simples, pero estoy de acuerdo con el uso de IEnumerable para las interfaces para que ambos tengamos razón. –

+1

@Steven: elegí 'List ' simplemente porque a) usa matrices en el back-end, por lo que realmente no está perdiendo nada, yb) le permite ser coherente con los conjuntos que comienzan con tamaños conocidos y desconocidos . Una lista también proporciona flexibilidad si necesita exponerla más adelante, ya que se puede leer fácilmente mediante la función 'AsReadOnly', mientras que una matriz requerirá un tipo completamente nuevo para que sea de solo lectura. –

+0

Buenas razones. Como refugiado de C++, encuentro que List es un reemplazo adecuado para vector. –

2

Hay dos principios básicos a tener en cuenta con respecto a la eficiencia de los recursos.

  • Runtime complejidad
  • Sobrecarga de la memoria

Usted ha dicho que los índices y el orden no importan y que una operación frecuente es coincidente. Un Dictionary<T> (que es un hashtable) es un candidato ideal para este tipo de trabajo. Las búsquedas en las teclas son muy rápidas, lo que sería beneficioso en su operación de coincidencia. La desventaja es que consumirá un poco más de memoria de lo estrictamente necesario. El factor de carga habitual es alrededor de .8 por lo que no estamos hablando de un gran aumento ni nada.

Para sus otras operaciones, puede encontrar que una matriz o List<T> es una mejor opción, especialmente si no necesita tener las búsquedas rápidas. Siempre que no necesite un alto rendimiento en operaciones especiales (búsquedas, clasificación, etc.), entonces es difícil superar las características generales de los recursos de los contenedores basados ​​en matrices.

+0

Usar un 'HashSet' sería mejor, imo, ya que no necesita un valor asociado con las teclas. – tzaman

+0

Si las búsquedas y/o comprobaciones para ver si un objeto existe en la colección sería mucho más frecuente que la modificación de la lista, entonces 'Dictionary' y' Hashset' serían buenos candidatos, pero solo para una "bolsa" general, introducen una pequeña cantidad de complejidad desperdiciada –

+0

@tzaman: Buen punto. –

0

La lista es probablemente buena en general. Es fácil de entender (en el sentido de la programación alfabetizada) y razonablemente eficiente. Las colecciones con clave (por ejemplo, Dict, SortedList) lanzarán una excepción si agrega una entrada con una clave duplicada, aunque esto puede no ser un problema para lo que está trabajando ahora.

Solo si encuentra que se encuentra con un problema de tiempo de CPU o de tamaño de memoria debería mejorar la "eficiencia", y solo después de determinar este es el cuello de botella.

Independientemente del enfoque que utilice, aún habrá creación y eliminación de los objetos subyacentes (colección o iterador) que eventualmente serán recolectados, si la aplicación se ejecuta lo suficiente.

Cuestiones relacionadas