Gibt es einen Grund für C#'s wiederverwenden der Variablen in einer foreach?

Bei der Verwendung von lambda-Ausdrücke oder anonyme Methoden in C#, wir müssen vorsichtig sein, die Zugang zu modifizierten Verschluss Falle. Zum Beispiel:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); //access to modified closure
   ...
}

Durch die veränderte Schließung der obige code bewirkt, dass alle von der Where Klauseln, die auf der Abfrage basieren auf den endgültigen Wert von s.

Erläutert hier, dies geschieht, weil die s variable deklariert foreach Schleife oben übersetzt wird, wie dies in den compiler:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}

statt so:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;
   ...
}

Als darauf hingewiesen,hier, gibt es keine performance-Vorteile zu deklarieren einer Variablen außerhalb der Schleife, und unter normalen Umständen der einzige Grund, der mir einfällt, dies zu tun ist, wenn Sie planen, verwenden Sie die variable außerhalb der Schleife:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
var finalString = s;

Jedoch Variablen definiert foreach Schleife kann nicht verwendet werden, außerhalb der Schleife:

foreach(string s in strings)
{
}
var finalString = s; //won't work: you're outside the scope.

Damit der compiler deklariert die variable in einer Weise, die macht es sehr anfällig für Fehler, die oft schwer zu finden und zu Debuggen, während der Produktion keine wahrnehmbaren Vorteile.

Gibt es etwas, was Sie tun können, mit foreach Schleifen diese Weise, dass Sie konnten nicht, wenn Sie kompiliert wurden, mit einem inneren Gültigkeitsbereich variable, oder ist dies nur eine willkürliche Wahl, die vorgenommen wurde, bevor die anonyme Methoden und lambda-Ausdrücke zur Verfügung standen oder gemeinsam, und die bisher nicht überarbeitet, da Sie dann?

Was ist falsch mit String s; foreach (s in strings) { ... }?
die OP ist wirklich nicht sprechen foreachaber über lamda-Ausdrücke resultieren in ähnlichen code wie gezeigt, durch die OP...
Nicht, dass kompilieren? (Fehler: Typ und id sind beide erforderlich, in einer foreach-Anweisung für mich)
Es ist ein geschlossen-über äußere lokalen einer lambda; warum bist du davon aus, dass es sich dabei auf dem stack? Es ist Leben, ist länger als der stack-frame!
Ich bin verwirrt. Ich verstehe, dass lambda fängt einen Verweis auf die foreach-variable (was ist intern, erklärt außerhalb die Schleife) und damit Sie am Ende den Vergleich gegen seinen endgültigen Wert; ich bekomme. Was ich nicht verstehe ist, wie man das deklarieren der variable inside die Schleife wird überhaupt einen Unterschied. Aus einer compiler-writer Sicht ich bin nur die Zuweisung einer string-Referenz (var 's') auf dem Stapel, unabhängig davon, ob die Erklärung innerhalb oder außerhalb der Schleife; ich würde sicherlich nicht wollen, schieben Sie eine neue Referenz auf den stack jeder iteration!

InformationsquelleAutor StriplingWarrior | 2012-01-17

Schreibe einen Kommentar