Es lohnt re ading up on how foreach
works (nicht nur für diese Frage, sondern als eine Angelegenheit von allgemeinem Interesse): Es erhält einen Enumerator (überraschend breit definiert) aus dem Ergebnis des Ausdrucks rechts von in
und ruft dann bool MoveNext()
auf diesem Enumerator, bis MoveNext()
zurückgibt falsch.
Es würde keinen Sinn ergeben, foreach
wiederholt den Ausdruck auszuwerten, aus dem es den Enumerator bezieht. In der Tat, .NET ist sehr bemüht, Sie daran zu hindern, eine Sequenz zu ändern, während sie aufgezählt wird - mit anderen Worten, um sicherzustellen, dass sie genau das gleiche aufzählt, mit dem sie begonnen hat. Versuchen Sie, ein Element an einen List<T>
Hinzufügen, während Sie in einer foreach drauf sind:
var list = Enumerable.Range(0, 10).ToList();
foreach (var x in list)
{
list.Add(x);
}
„Collection modifiziert wurde; Enumerationsvorgang nicht ausgeführt werden kann.“
Kein Verkauf.
Und wenn es neue Enumeratoren bekommen würde, müsste es Elemente in ihnen überspringen. Erste Iteration, erstes Element holen. Zweitens: Nimm einen neuen Enumerator, überspringe ihn, nimm den nächsten. Drittens: Besorgen Sie sich einen neuen Enumerator, überspringen Sie zwei, springen Sie von einer Brücke.
Das ist Wahnsinn. Es ist keine Möglichkeit für Profis, Code oder sogar halbnüchterne Amateure zu schreiben.
Also, es ist nur mit dem Ergebnis Ihres Ausdrucks. Es spielt keine Rolle, ob der Ausdruck zufällig zwischen den Parens liegt oder ob Sie das Ergebnis einer lokalen Variablen zugewiesen haben.
Beide Versionen sind identisch.
Es gibt auch die Möglichkeit von potenziell offenen Enumerationen - etwas in dort könnte auf einem parallelen Thread sitzen, in der Warteschlange von Zeug aus einem Gerätetreiber oder etwas, und die Enumeration nicht unbedingt enden. Aber Sie würden immer noch den gleichen Enumerator aus beiden Versionen Ihres Codes erhalten.
Nein, das wäre lächerlich. Welchen Sinn würde es machen, bei jeder Iteration einen neuen Iterator zu bekommen? –
Durch Hinzufügen einer, wo Sie unterschiedliche Ausführung erhalten, weil Sie jetzt auf ein IEnumerable handeln, wird die Bedingung bei jeder Iteration überprüft, aber wenn Sie diese konditionierte Aufzählung mehrmals verwenden müssten, wäre es etwas optimaler zu drehen dass IEnumerable zurück in eine Liste –
Sie tun genau das gleiche –