Wenn Sie einen Reader iterieren müssen, bei dem die Anzahl der zu lesenden Elemente unbekannt ist, und die einzige Möglichkeit besteht darin, weiterzulesen, bis Sie das Ende erreicht haben.
Dies ist oft der Ort, an dem Sie eine Endlosschleife benötigen.
Es gibt das Immer
true
, das anzeigt, dass irgendwo innerhalb des Blocks einbreak
oder einereturn
Anweisung stehen muss .int offset = 0; while(true) { Record r = Read(offset); if(r == null) { break; } // do work offset++; }
Es gibt die Double Read for Loop-Methode.
Record r = Read(0); for(int offset = 0; r != null; offset++) { r = Read(offset); if(r != null) { // do work } }
Es gibt die Single Read While-Schleife. Nicht alle Sprachen unterstützen diese Methode .
int offset = 0; Record r = null; while((r = Read(++offset)) != null) { // do work }
Ich frage mich, welcher Ansatz mit der geringsten Wahrscheinlichkeit einen Fehler verursacht, der am besten lesbar und am häufigsten verwendet wird.
Jedes Mal, wenn ich eines davon schreiben muss, denke ich, dass es einen besseren Weg geben muss .
c#
code-quality
readability
Reactgular
quelle
quelle
Antworten:
Ich würde hier einen Schritt zurück machen. Sie konzentrieren sich auf die wählerischen Details des Codes, übersehen aber das größere Bild. Werfen wir einen Blick auf eine Ihrer Beispielschleifen:
Was bedeutet dieser Code? Die Bedeutung ist "Arbeiten Sie an jedem Datensatz in einer Datei". Aber so sieht der Code nicht aus . Der Code sieht wie folgt aus: "Versatz beibehalten. Datei öffnen. Schleife ohne Endebedingung eingeben. Datensatz lesen. Auf Nullheit prüfen." Das alles, bevor wir zur Arbeit kommen! Die Frage, die Sie stellen sollten, lautet: " Wie kann ich sicherstellen, dass das Erscheinungsbild dieses Codes mit der Semantik übereinstimmt? "
Jetzt liest sich der Code wie beabsichtigt. Trennen Sie Ihre Mechanismen von Ihrer Semantik . In Ihrem ursprünglichen Code mischen Sie den Mechanismus - die Details der Schleife - mit der Semantik - der Arbeit, die für jeden Datensatz geleistet wurde.
Jetzt müssen wir umsetzen
RecordsFromFile()
. Wie lässt sich das am besten umsetzen? Wen interessiert das? Das ist nicht der Code, den sich irgendjemand ansehen wird. Es ist ein grundlegender Mechanismuscode und seine zehn Zeilen lang. Schreibe es wie du willst. Wie wäre es damit?Jetzt, da wir eine träge berechnete Folge von Datensätzen manipulieren, werden alle möglichen Szenarien möglich:
Und so weiter.
Fragen Sie sich, wann immer Sie eine Schleife schreiben: "Liest diese Schleife wie ein Mechanismus oder wie die Bedeutung des Codes?" Wenn die Antwort "wie ein Mechanismus" ist, versuchen Sie, diesen Mechanismus auf seine eigene Methode zu verschieben, und schreiben Sie den Code, um die Bedeutung sichtbarer zu machen.
quelle
Sie brauchen keine Endlosschleife. In C # -Leseszenarios sollten Sie niemals eines benötigen. Dies ist mein bevorzugter Ansatz, vorausgesetzt, Sie müssen wirklich einen Offset beibehalten:
Dieser Ansatz erkennt die Tatsache an, dass es einen Einrichtungsschritt für den Leser gibt, sodass zwei Lesemethodenaufrufe vorhanden sind. Die
while
Bedingung befindet sich ganz oben in der Schleife, nur für den Fall, dass der Reader überhaupt keine Daten enthält.quelle
Nun, es hängt von Ihrer Situation ab. Aber eine der "C # -ish" -Lösungen, die ich mir vorstellen kann, ist die Verwendung der integrierten IEnumerable-Schnittstelle und einer foreach-Schleife. Die Schnittstelle für IEnumerator ruft MoveNext nur mit true oder false auf, sodass die Größe unbekannt sein kann. Dann wird Ihre Terminierungslogik einmal im Enumerator geschrieben und Sie müssen nicht mehr als an einer Stelle wiederholen.
MSDN enthält ein Beispiel für IEnumerator <T> . Sie müssen auch ein IEnumerable <T> erstellen, um den IEnumerator <T> zurückzugeben.
quelle
Wenn ich Initialisierungs-, Bedingungs- und Inkrementierungsoperationen habe, verwende ich gerne die for-Schleifen von Sprachen wie C, C ++ und C #. So was:
Oder dies, wenn Sie denken, dass dies besser lesbar ist. Ich persönlich bevorzuge den ersten.
quelle