411 votes

Dans .NET, qui boucle s'exécute plus rapidement, 'pour' ou 'foreach'?

En C#/VB.NET/.NET, qui boucle s'exécute plus rapidement, for ou foreach?

Depuis que j'ai lu qu'un for boucle fonctionne plus rapidement qu'un foreach boucle un il y a longtemps je suppose qu'il se tenait vrai pour toutes les collections, générique collections, tous les tableaux, etc.

J'ai parcouru Google et trouvé quelques articles, mais la plupart d'entre eux ne sont pas concluants (lire les commentaires sur les articles) et ouvertes.

Ce serait l'idéal est d'avoir chaque scénario et de la meilleure solution pour le même.

Par exemple (juste un exemple de la façon dont elle doit l'être):

  1. pour l'itération d'un tableau de 1000+ cordes - for est mieux que foreach
  2. pour parcourir IList (non générique) cordes - foreach est mieux qu' for

Quelques références trouvées sur le web pour la même chose:

  1. Original ancien grand article par Emmanuel Schanzer
  2. CodeProject FOREACH Vs. POUR
  3. Blog - foreach ou de non - foreach, telle est la question
  4. ASP.NET forum - NET 1.1 C# for vs foreach

[Modifier]

En dehors de la lisibilité de ses aspects, je suis vraiment intéressé par les faits et les chiffres. Il y a des applications où le dernier kilomètre de l'optimisation de la performance pressé la matière.

427voto

Ian Nelson Points 20020

Patrick Smacchia blogué à propos de ce dernier mois, avec les conclusions suivantes:

  • pour des boucles sur la Liste sont un peu plus de 2 fois moins cher que le foreach boucle sur la Liste.
  • Boucle sur le tableau est environ 2 fois moins cher qu'en boucle sur la Liste.
  • En conséquence, en boucle sur le tableau à l'aide de pour est 5 fois moins cher que l'on boucle sur les Liste en utilisant foreach (qui, je crois, est ce que nous faisons tous).

181voto

Jon Skeet Points 692016

Tout d'abord, une demande reconventionnelle de Dmitry réponse. Pour les tableaux, le compilateur C# émet en grande partie le même code pour foreach comme elle le ferait pour un équivalent for boucle. Qui explique pourquoi, pour ce cas-test, les résultats sont sensiblement les mêmes:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 1000000;
    const int Iterations = 10000;

    static void Main()
    {
        double[] data = new double[Size];
        Random rng = new Random();
        for (int i=0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }

        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j=0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop: {0}", sw.ElapsedMilliseconds);
    }
}

Résultats:

For loop: 16638
Foreach loop: 16529

Ensuite, la validation de Greg point sur le type de collection d'important changement de la matrice à une List<double> ci-dessus, et vous obtenez radicalement différents résultats. Non seulement est-il significativement plus lente en général, mais foreach devient beaucoup plus lent que l'accès par index. Cela dit, je serais encore presque toujours préférer une boucle foreach pour une boucle où il rend le code plus simple - parce que la lisibilité est presque toujours important, tandis que les micro-optimisation de l'est rarement.

164voto

ctford Points 3599

foreach boucles de faire preuve de plus de l'intention spécifique de for boucles.

À l'aide d'un foreach boucle démontre à toute personne utilisant votre code que vous envisagez de faire quelque chose pour chaque membre d'une collection, indépendamment de sa place dans la collection. Elle vous permet également de ne pas modifier l'original de la collection (et lève une exception si vous essayez d').

L'autre avantage de l' foreach , c'est qu'il fonctionne sur n'importe quel IEnumerable, lorsque, comme en for n'a de sens que pour l' IList, où chaque élément a un index.

Toutefois, si vous avez besoin d'utiliser l'index d'un élément, puis de sûr, vous devriez être autorisé à utiliser un for boucle. Mais si vous n'avez pas besoin d'utiliser un index, il est juste encombrer votre code.

Il n'y a pas d'importantes implications sur les performances autant que je suis au courant. À un certain moment dans l'avenir, il serait plus facile d'adapter le code à l'aide foreach pour s'exécuter sur plusieurs cœurs, mais ce n'est pas quelque chose à craindre maintenant.

53voto

Rob Fonseca-Ensor Points 11697

De tout temps il y a des arguments plus de performances, vous avez juste besoin d'écrire un petit test de sorte que vous pouvez utiliser quantitative des résultats à l'appui.

Utiliser le Chronomètre de classe et de répéter quelque chose de quelques millions de fois, pour plus de précision. (Cela peut être difficile sans un pour la boucle):

using System.Diagnostics;
//...
Stopwatch sw = new Stopwatch()
sw.Start()
for(int i = 0; i < 1000000;i ++)
{
    //do whatever it is you need to time
}
sw.Stop();
//print out sw.ElapsedMilliseconds

Nous croisons les doigts pour les résultats de ce spectacle que la différence est négligeable, et vous pourriez tout aussi bien faire ce que les résultats dans les plus maintenable code

53voto

Marc Gravell Points 482669

Il sera toujours à proximité. Pour un tableau, parfois, for est légèrement plus rapide, mais foreach est plus expressive, et offre LINQ, etc. En général, tenez - foreach.

En outre, foreach , peut être optimisé dans certains scénarios. Par exemple, une liste pourrait être terrible par l'indexeur, mais il pourrait être rapide en foreach. En fait, la norme LinkedList<T> n'offrent même pas un indexeur pour cette raison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X