uso new for features espaƱol definicion bucle c# performance loops

new - foreach c# list



Diferencia entre foreach y for bucles sobre una clase IEnumerable en C# (7)

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; }

Me han dicho que hay 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 soy un CLR esperado, pero por lo que puedo decir, deberían reducirse básicamente al mismo código. ¿Alguien tiene evidencia concreta (diablos, tomaría basura compactada) de una forma u otra?


Aquí falta un punto: una lista tiene una propiedad Count, internamente hace un seguimiento de cuántos elementos hay en ella.

Un IEnumerable NO LO HACE.

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

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

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

Si desea flexibilidad, use foreach y programe IEnumerable. (lo que permite el uso de linq y / o retorno de rendimiento).


Creo que una posible situación en la que puede obtener una ganancia de rendimiento es si el tamaño del tipo enumerable y la condición de ciclo son una constante; 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 si el compilador .NET hace esto, y tiene una utilidad limitada si el tamaño del tipo enumerable es dinámico.

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

Personalmente, generalmente no me preocupa y uso foreach cada vez que necesito todos los artículos y no me importa el índice del artículo. Si no estoy trabajando con todos los elementos o realmente necesito saber el índice, uso para. La única vez que pude ver que era una gran preocupación es con estructuras como listas vinculadas.


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


La muestra 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 ciclo regular for no tiene que pagar:

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

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

No se reducen al mismo código de ninguna manera, en realidad, que verías si escribieras tu propio enumerador.


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

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