Pregunta

Me han dicho que existe una diferencia de rendimiento entre los siguientes bloques de código.

foreach (Entity e in entityList)
{
 ....
}

y

for (int i=0; i<entityList.Count; i++)
{
   Entity e = (Entity)entityList[i];
   ...
}

dónde

List<Entity> entityList;

No espero CLR, pero por lo que puedo decir, deberían reducirse básicamente al mismo código.¿Alguien tiene evidencia concreta (diablos, yo elegiría tierra compacta) de una forma u otra?

¿Fue útil?

Solución

foreach crea una instancia de un enumerador (devuelto por GetEnumerator) y ese enumerador también mantiene el estado durante todo el ciclo foreach.Luego llama repetidamente al objeto Next() en el enumerador y ejecuta su código para cada objeto que devuelve.

En realidad, no se reducen al mismo código de ninguna manera, lo cual verías si escribieras tu propio enumerador.

Otros consejos

Aquí es un buen artículo que muestra las diferencias de IL entre los dos bucles.

Foreach es técnicamente más lento, pero mucho más fácil de usar y de leer.A menos que el rendimiento sea crítico, prefiero el bucle foreach al bucle for.

El ejemplo de foreach corresponde aproximadamente a este código:

using(IEnumerator<Entity> e = entityList.GetEnumerator()) {
    while(e.MoveNext()) {
        Entity entity = e.Current;
        ...
    }
}

Aquí hay dos costos que un bucle for normal no tiene que pagar:

  1. El costo de asignar el objeto enumerador mediante entidadList.GetEnumerator().
  2. El costo de dos llamadas a métodos virtuales (MoveNext y Current) para cada elemento de la lista.

Un punto se perdió aquí:Una Lista tiene una propiedad Count, internamente realiza un seguimiento de cuántos elementos hay en ella.

Un IEnumerable NO LO HACE.

Si programa en la interfaz IEnumerable y usa el método de extensión de conteo, se enumerará solo para contar los elementos.

Sin embargo, es un punto discutible ya que en IEnumerable no se puede hacer referencia a elementos por índice.

Entonces, si desea bloquear listas y matrices, puede obtener pequeños aumentos de rendimiento.

Si desea flexibilidad, utilice foreach y programe en IEnumerable.(permitiendo el uso de linq y/o rendimiento de retorno).

En términos de asignaciones, sería mejor mirar esta publicación de blog.Muestra exactamente en qué circunstancias se asigna un enumerador en el montón.

Creo que una posible situación en la que podría obtener una ganancia de rendimiento es si el tamaño del tipo enumerable y la condición del bucle son constantes;Por ejemplo:

const int ArraySize = 10;
int[] values = new int[ArraySize];

//...

for (int i = 0; i 

En este caso, dependiendo de la complejidad del cuerpo del bucle, el compilador podría reemplazar el bucle con llamadas en línea.No tengo idea de si el compilador .NET hace esto y es de utilidad limitada si el tamaño del tipo enumerable es dinámico.

Una situación donde foreach podría funcionar mejor con estructuras de datos como una lista vinculada donde el acceso aleatorio significa atravesar la lista;el enumerador utilizado por foreach probablemente iterará un elemento a la vez, haciendo que cada acceso sea O(1) y el bucle completo O(n), pero llamar al indexador significa comenzar desde el principio y encontrar el elemento en el índice correcto;O(N) cada bucle para O(n^2).

Personally I don't usually worry about it and use foreach any time I need all items and don't care about the index of the item. If I'm not working with all of the items or I really need to know the index, I use for.La única vez que pude verlo como una gran preocupación es con estructuras como listas vinculadas.

For Loop
for loop is used to perform the opreration n times
for(int i=0;i<n;i++)
{
l=i;
}
foreach loop

int[] i={1,2,3,4,5,6}
foreach loop is used to perform each operation value/object in IEnumarable 
foreach(var k in i)
{
l=k;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top