Unterschied zwischen foreach- und for-Schleifen über eine IEnumerable-Klasse in C#

StackOverflow https://stackoverflow.com/questions/44220

  •  09-06-2019
  •  | 
  •  

Frage

Mir wurde gesagt, dass es einen Leistungsunterschied zwischen den folgenden Codeblöcken gibt.

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

Und

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

Wo

List<Entity> entityList;

Ich erwarte keine CLR, aber soweit ich das beurteilen kann, sollten sie im Wesentlichen auf denselben Code hinauslaufen.Hat irgendjemand konkrete (verdammt, ich würde gepackten Dreck nehmen) Beweise für die eine oder andere Weise?

War es hilfreich?

Lösung

foreach erstellt eine Instanz eines Enumerators (zurückgegeben von GetEnumerator) und dieser Enumerator behält auch während der gesamten foreach-Schleife seinen Status bei.Anschließend ruft es wiederholt das Next()-Objekt im Enumerator auf und führt Ihren Code für jedes zurückgegebene Objekt aus.

Sie laufen eigentlich nicht auf denselben Code hinaus, was Sie sehen würden, wenn Sie Ihren eigenen Enumerator schreiben würden.

Andere Tipps

Hier ist ein guter Artikel, der die IL-Unterschiede zwischen den beiden Schleifen zeigt.

Foreach ist technisch langsamer, aber viel einfacher zu verwenden und leichter zu lesen.Sofern die Leistung nicht entscheidend ist, bevorzuge ich die foreach-Schleife gegenüber der for-Schleife.

Das foreach-Beispiel entspricht ungefähr diesem Code:

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

Hier fallen zwei Kosten an, die eine reguläre for-Schleife nicht bezahlen muss:

  1. Die Kosten für die Zuweisung des Enumeratorobjekts durch entityList.GetEnumerator().
  2. Die Kosten für zwei virtuelle Methodenaufrufe (MoveNext und Current) für jedes Element der Liste.

Ein Punkt fehlt hier:Eine Liste verfügt über eine Count-Eigenschaft. Sie verfolgt intern, wie viele Elemente darin enthalten sind.

Ein IEnumerable NICHT.

Wenn Sie die Schnittstelle IEnumerable programmieren und die Count-Extension-Methode verwenden, werden nur die Elemente gezählt.

Ein strittiger Punkt, da Sie im IEnumerable nicht über den Index auf Elemente verweisen können.

Wenn Sie sich also an Listen und Arrays binden möchten, können Sie geringfügige Leistungssteigerungen erzielen.

Wenn Sie Flexibilität wünschen, verwenden Sie foreach und programmieren Sie auf IEnumerable.(ermöglicht die Verwendung von Linq und/oder Yield Return).

Was die Zuteilungen angeht, wäre es besser, einen Blick darauf zu werfen dieser Blogbeitrag.Es zeigt genau, unter welchen Umständen ein Enumerator auf dem Heap zugewiesen wird.

Ich denke, eine mögliche Situation, in der Sie könnte Einen Leistungsgewinn erzielen Sie, wenn die Größe des aufzählbaren Typs und die Schleifenbedingung eine Konstante sind.Zum Beispiel:

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

//...

for (int i = 0; i 

In diesem Fall kann der Compiler je nach Komplexität des Schleifenkörpers die Schleife möglicherweise durch Inline-Aufrufe ersetzen.Ich habe keine Ahnung, ob der .NET-Compiler dies tut, und es ist von begrenztem Nutzen, wenn die Größe des aufzählbaren Typs dynamisch ist.

Eine Situation, in der foreach Eine bessere Leistung könnte bei Datenstrukturen wie einer verknüpften Liste erzielt werden, bei der wahlfreier Zugriff das Durchlaufen der Liste bedeutet.Der Enumerator, der von verwendet wird foreach wird wahrscheinlich ein Element nach dem anderen iterieren, wobei jeder Zugriff O(1) und die vollständige Schleife O(n) ist, aber der Aufruf des Indexers bedeutet, am Kopf zu beginnen und das Element am richtigen Index zu finden;O(N) jede Schleife für 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.Das einzige Mal, dass ich ein großes Problem erkennen konnte, waren Strukturen wie verknüpfte Listen.

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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top