Question

On m'a dit qu'il existe une différence de performances entre les blocs de code suivants.

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

et

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

List<Entity> entityList;

Je ne m'attends pas à du CLR, mais d'après ce que je peux dire, ils devraient se résumer essentiellement au même code.Quelqu'un a-t-il des preuves concrètes (bon sang, je prendrais de la terre emballée) dans un sens ou dans l'autre ?

Était-ce utile?

La solution

foreach crée une instance d'un énumérateur (renvoyée par GetEnumerator) et cet énumérateur conserve également son état tout au long de la boucle foreach.Il appelle ensuite à plusieurs reprises l'objet Next() sur l'énumérateur et exécute votre code pour chaque objet qu'il renvoie.

Ils ne se résument en aucun cas au même code, ce que vous verriez si vous écriviez votre propre énumérateur.

Autres conseils

Ici est un bon article qui montre les différences IL entre les deux boucles.

Foreach est techniquement plus lent mais beaucoup plus facile à utiliser et à lire.À moins que les performances ne soient critiques, je préfère la boucle foreach à la boucle for.

L'échantillon foreach correspond à peu près à ce code :

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

Il y a ici deux coûts qu'une boucle for régulière n'a pas à payer :

  1. Le coût d’allocation de l’objet énumérateur parentityList.GetEnumerator().
  2. Le coût de deux appels de méthodes virtuelles (MoveNext et Current) pour chaque élément de la liste.

Un point manqué ici:Une liste a une propriété Count, elle garde en interne une trace du nombre d’éléments qu’elle contient.

Un IEnumerable NE LE FAIT PAS.

Si vous programmez sur l'interface IEnumerable et utilisez la méthode d'extension count, elle énumérera uniquement pour compter les éléments.

Un point discutable cependant puisque dans IEnumerable, vous ne pouvez pas faire référence aux éléments par index.

Ainsi, si vous souhaitez vous connecter aux listes et aux tableaux, vous pouvez obtenir de légères augmentations de performances.

Si vous souhaitez de la flexibilité, utilisez foreach et programmez IEnumerable.(permettant l'utilisation de linq et/ou de rendement return).

En termes d'allocations, il vaudrait mieux regarder cet article de blog.Il montre exactement dans quelles circonstances un énumérateur est alloué sur le tas.

Je pense qu'une situation possible où vous pourrait obtenir un gain de performances si la taille du type énumérable et la condition de boucle sont une constante ;Par exemple:

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

//...

for (int i = 0; i 

Dans ce cas, en fonction de la complexité du corps de la boucle, le compilateur pourra peut-être remplacer la boucle par des appels en ligne.Je ne sais pas si le compilateur .NET fait cela, et son utilité est limitée si la taille du type énumérable est dynamique.

Une situation où foreach pourrait mieux fonctionner avec des structures de données comme une liste chaînée où l'accès aléatoire signifie parcourir la liste;l'enquêteur utilisé par foreach itérera probablement un élément à la fois, rendant chaque accès O(1) et la boucle complète O(n), mais appeler l'indexeur signifie commencer par la tête et trouver l'élément au bon index ;O(N) chaque boucle pour 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 seule fois où j’ai pu voir que cela constitue une grande préoccupation, c’est avec des structures telles que les listes chaînées.

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top