440 Stimmen

Welche Schleife in .NET läuft schneller, "for" oder "foreach"?

In C#/VB.NET/.NET, welche Schleife läuft schneller, for o foreach ?

Seitdem ich gelesen habe, dass ein for Schleife arbeitet schneller als eine foreach Schleife a vor langer Zeit Ich nahm an, dass dies für alle Sammlungen, generischen Sammlungen, alle Arrays usw. gilt.

Ich habe Google durchforstet und einige Artikel gefunden, aber die meisten davon sind nicht schlüssig (lesen Sie die Kommentare zu den Artikeln) und haben ein offenes Ende.

Ideal wäre es, jedes Szenario aufzulisten und die beste Lösung dafür zu nennen.

Ein Beispiel (nur ein Beispiel dafür, wie es sein sollte):

  1. für die Iteration eines Arrays von 1000+ Zeichenketten - for ist besser als foreach
  2. zur Iteration über IList (nicht generische) Zeichenketten - foreach ist besser als for

Ein paar Referenzen im Internet für das gleiche gefunden:

  1. Ursprünglicher großer alter Artikel von Emmanuel Schanzer
  2. CodeProject FOREACH Vs. FOR
  3. Blog - Zum foreach oder nicht foreach das ist die Frage
  4. ASP.NET Forum - NET 1.1 C# for vs foreach

[Bearbeiten]

Abgesehen vom Aspekt der Lesbarkeit bin ich wirklich an Fakten und Zahlen interessiert. Es gibt Anwendungen, bei denen es auf die letzte Meile der Leistungsoptimierung ankommt.

451voto

Ian Nelson Punkte 53679

Patrick Smacchia darüber gebloggt im vergangenen Monat mit den folgenden Schlussfolgerungen:

  • for-Schleifen auf List sind etwas mehr als 2-mal billiger als foreach Schleifen für List.
  • Eine Schleife über ein Array ist etwa 2-mal billiger als eine Schleife über eine Liste.
  • Infolgedessen ist die Schleifenbildung auf einem Array mit for 5 Mal billiger als eine Schleife über eine Liste mit foreach (was wir, glaube ich, alle tun).

188voto

Jon Skeet Punkte 1325502

Erstens, eine Widerklage gegen Dmitrys (inzwischen gelöschte) Antwort . Für Arrays gibt der C#-Compiler weitgehend den gleichen Code für foreach wie bei einem entsprechenden for Schleife. Das erklärt, warum die Ergebnisse bei diesem Benchmark im Wesentlichen gleich sind:

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

Ergebnisse:

For loop: 16638
Foreach loop: 16529

Als Nächstes validieren Sie den Punkt von Greg, dass der Auflistungstyp wichtig ist - ändern Sie das Array in eine List<double> in die obige Tabelle ein, und Sie erhalten völlig andere Ergebnisse. Es ist nicht nur deutlich langsamer im Allgemeinen, sondern foreach wird deutlich langsamer als der Zugriff nach Index. Abgesehen davon, würde ich immer noch fast immer foreach einer for-Schleife vorziehen, wenn der Code dadurch einfacher wird - denn die Lesbarkeit ist fast immer wichtig, die Mikro-Optimierung dagegen selten.

169voto

ctford Punkte 7069

foreach Schleifen zeigen eine spezifischere Absicht als for Schleifen .

Mit einer foreach Schleife zeigt jedem, der Ihren Code verwendet, dass Sie planen, mit jedem Mitglied einer Sammlung etwas zu tun, unabhängig von seinem Platz in der Sammlung. Sie zeigt auch, dass Sie die ursprüngliche Sammlung nicht verändern (und löst eine Ausnahme aus, wenn Sie dies versuchen).

Der andere Vorteil von foreach ist, dass es auf jedem IEnumerable , wobei als for ist nur sinnvoll für IList , wobei jedes Element tatsächlich einen Index hat.

Wenn Sie jedoch den Index eines Elements verwenden müssen, dann sollten Sie natürlich die Möglichkeit haben, eine for Schleife. Aber wenn Sie einen Index nicht brauchen, wird Ihr Code dadurch nur unübersichtlich.

Soweit ich weiß, gibt es keine wesentlichen Auswirkungen auf die Leistung. Irgendwann in der Zukunft könnte es einfacher sein, den Code mit foreach auf mehreren Kernen laufen zu lassen, aber das ist im Moment kein Grund zur Sorge.

55voto

Marc Gravell Punkte 970173

Es wird immer eng sein. Für ein Array, manchmal for ist etwas schneller, aber foreach ist aussagekräftiger und bietet LINQ usw. Im Allgemeinen sollten Sie bei foreach .

Zusätzlich, foreach kann in einigen Szenarien optimiert werden. Eine verknüpfte Liste kann zum Beispiel für den Indexer schrecklich sein, aber sie kann schnell sein durch foreach . Eigentlich ist der Standard LinkedList<T> bietet aus diesem Grund nicht einmal einen Indexer an.

54voto

Rob Fonseca-Ensor Punkte 15345

Wann immer es Streit um die Leistung gibt, müssen Sie einfach einen kleinen Test schreiben, damit Sie Ihre Argumente durch quantitative Ergebnisse untermauern können.

Verwenden Sie die Klasse StopWatch und wiederholen Sie etwas ein paar Millionen Mal, um genau zu sein. (Dies könnte ohne eine for-Schleife schwierig sein):

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

Ich drücke die Daumen, dass die Ergebnisse zeigen, dass der Unterschied vernachlässigbar ist und man einfach das tun kann, was den am besten zu wartenden Code ergibt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X