2010-03-15 4 views
34

Was ist die beste Vorgehensweise beim Umgang mit Objekten in for- oder foreach-Schleifen? Sollten wir ein Objekt außerhalb der Schleifen erstellen und es erneut (mit neuen ...) neu erstellen oder für jede Schleifeniteration ein neues erstellen?
Beispiel:Bewährte Methode zum Erstellen von Objekten, die in for/foreach-Schleifen verwendet werden

foreach(var a in collection) 
{ 
    SomeClass sc = new SomeClass(); 
    sc.id = a; 
    sc.Insert(); 
} 

oder

SomeClass sc = null; 
foreach(var a in collection) 
{ 
    sc = new SomeClass(); 
    sc.id = a; 
    sc.Insert(); 
} 

Was ist besser?

Antwort

67

Der erste Weg ist besser, da er den beabsichtigten Umfang der Variablen deutlicher vermittelt und verhindert, dass Fehler versehentlich ein Objekt außerhalb des beabsichtigten Bereichs verwenden.

Ein Grund für die Verwendung der zweiten Form ist, wenn Sie aus der Schleife ausbrechen und immer noch einen Verweis auf das Objekt haben möchten, das Sie zuletzt in der Schleife erreicht haben.

Ein schlechter Grund für die Wahl der zweiten Form ist die Leistung. Es mag auf den ersten Blick scheinen, dass die zweite Methode weniger Ressourcen verbraucht oder dass Sie nur ein Objekt erstellen und es wiederverwenden. Dies ist hier nicht der Fall. Die wiederholte Deklaration einer Variablen innerhalb einer Schleife verbraucht keine zusätzlichen Ressourcen oder Taktzyklen, so dass Sie keinen Leistungsvorteil beim Ziehen der Deklaration außerhalb der Schleife erhalten.

+3

+1 - Objekte sollten nur dort deklariert werden, wo und wann sie benötigt werden. Wenn Sie int i in einer for-Schleife benötigen, deklarieren Sie es innerhalb der for-Schleife nicht an der Spitze des Funktionskörpers. Siehe Code abgeschlossen :). – JonH

+1

Bei der .Net-Variablendeklaration handelt es sich wirklich um Metadaten zur Methode. Die tatsächliche Position, an der die Variable in Code erstellt wird, wirkt sich nur auf den Bereich für den Compiler aus ... Mit anderen Worten gibt es keinen Leistungsunterschied zwischen diesen beiden Beispielen. –

+2

Es gab einmal geringfügige Unterschiede in der IL, die zwischen diesen beiden Schleifen erzeugt wurde (das gleiche gilt für Java und C++), aber nicht genug, um sich darum zu kümmern. Ich bin mir nicht sicher, ob die aktuellen Compiler das geändert haben oder ob die CLR die zusätzliche IL optimiert. –

4

Ich bin sicher, jemand könnte die MSIL-Analyse herauspeitschen, aber praktisch gibt es keinen erkennbaren Unterschied in der Ausführung oder Leistung. Das einzige, was Sie beeinflussen, ist das Speichern einer Objektreferenz.

Ich sage, halten Sie es sauber und einfach; Deklarieren Sie die Variable innerhalb der Schleife. Dies stellt das Prinzip "offen/geschlossen" in der Praxis dar, so dass Sie den Gültigkeitsbereich der Variablen kennen und nicht anderweitig verwendet werden. Bei der nächsten Schleife verliert die Variable den Umfang und wird automatisch neu initialisiert.

1

Ich denke, es spielt keine Rolle für die Leistung, aber ich bevorzuge die erste. Ich versuche immer, Deklaration und Instanziierung möglichst zusammen zu halten.

+0

'Go to Definition' ist viel nützlicher, wenn das Objekt tatsächlich gesetzt und nicht deklariert wird. – cjk

3

Sie erstellen in beiden Fällen ein neues Objekt in jeder Schleifeniteration (seit dem Aufruf new SomeClass()).

Der frühere Ansatz macht deutlich, dass sc nur innerhalb der Schleife verwendet wird, was unter Wartungsgesichtspunkten von Vorteil sein kann.

0

Ich würde die erste verwenden, aber für Compiler ist es das gleiche, weil Compiler Deklaration von Variablen aus den Schleifen verschiebt. Ich wette, nach dem Kompilieren würde der Code wie der zweite aussehen.

+0

Schließen. Die zweite erzeugt 2 zusätzliche IL-Befehle, ldnull und stloc.n, um null zu sc zuzuweisen. –

12

Zunächst einmal, ich beachte, dass Sie meinen "Variablen erstellen", wenn Sie sagen "Erstellen von Objekten". Die Objektreferenzen gehen in die Variablen, aber sie sind nicht die Variablen selbst.

Beachten Sie, dass das von Ihnen beschriebene Szenario einen semantischen Unterschied einführt, wenn die Schleife eine anonyme Funktion enthält und die Variable eine geschlossene äußere Variable der anonymen Funktion ist. Siehe

http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/

für weitere Einzelheiten.

1

Ich würde mit Option 2 gehen, um ordentlich zu sein, alle Deklarationen an einem Ort zu halten. Sie können sagen, dass "Objekte sollten nur deklariert werden, wo und wann sie benötigt werden" aber Ihre Schleife würde wahrscheinlich in seiner eigenen kleinen Methode sein.

+1

Sagte wie ein C-Programmierer. – riwalk

Verwandte Themen