Ich möchte wissen, was als bessere Art der Rückgabe angesehen wird, wenn ich eine if
Erklärung habe.
Beispiel 1:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
else
{
myString = "Name " + myString;
// Do something more here...
return true;
}
}
Beispiel 2:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
myString = "Name " + myString;
// Do something more here...
return true;
}
Wie Sie in beiden Beispielen sehen können, wird die Funktion zurückgegeben. true/false
Ist es jedoch eine gute Idee, die else
Anweisung wie im ersten Beispiel zu platzieren, oder ist es besser, sie nicht zu platzieren?
else
.Antworten:
Beispiel 2 ist als Schutzblock bekannt. Es ist besser geeignet, eine Ausnahme frühzeitig zurückzugeben / auszulösen, wenn ein Fehler aufgetreten ist (falscher Parameter oder ungültiger Zustand). Im normalen logischen Ablauf ist es besser, Beispiel 1 zu verwenden
quelle
Mein persönlicher Stil ist es, die Single
if
für Guard Blocks und denif
/else
im eigentlichen Methodenverarbeitungscode zu verwenden.In diesem Fall verwenden Sie die
myString == null
als Schutzbedingung, daher würde ich eher das einzelneif
Muster verwenden.Betrachten Sie Code, der etwas komplizierter ist:
Beispiel 1:
Beispiel 2:
In Beispiel 1 haben sowohl der Guard als auch der Rest der Methode die Form
if
/else
. Vergleichen Sie dies mit Beispiel 2, in dem sich der Schutzblock in der einzelnenif
Form befindet, während der Rest der Methode die Formif
/else
verwendet. Ich persönlich finde Beispiel 2 einfacher zu verstehen, während Beispiel 1 unsauber und stark eingerückt aussieht.Beachten Sie, dass dies ein erfundenes Beispiel ist und dass Sie
else if
Anweisungen verwenden können, um es zu bereinigen, aber ich möchte den Unterschied zwischen Schutzblöcken und dem tatsächlichen Funktionsverarbeitungscode aufzeigen.Ein anständiger Compiler sollte sowieso für beide die gleiche Ausgabe erzeugen. Der einzige Grund, den einen oder anderen zu verwenden, ist die persönliche Präferenz oder die Anpassung an den Stil des vorhandenen Codes.
quelle
persönlich bevorzuge ich die zweite Methode. Ich habe das Gefühl, es ist kürzer, hat weniger Einrückungen und ist leichter zu lesen.
quelle
Meine persönliche Praxis ist die folgende:
Zum Beispiel:
Zum Beispiel:
Die "one exit" -Regel hilft auch, wenn die Berechnung externe Ressourcen erfordert, die Sie freigeben müssen, oder wenn Sie vor dem Verlassen der Funktion einen Reset durchführen müssen. manchmal werden sie später während der Entwicklung hinzugefügt. Bei mehreren Ausgängen im Algorithmus ist es viel schwieriger, alle Zweige ordnungsgemäß zu erweitern. (Und wenn Ausnahmen auftreten, sollte die Freigabe / Rücksetzung ebenfalls in einen Endblock gestellt werden, um in seltenen Ausnahmefällen Nebenwirkungen zu vermeiden ...).
Ihr Fall scheint in die Kategorie "Quick Exit Before Real Work" zu fallen, und ich würde es so schreiben wie Ihre Version in Beispiel 2.
quelle
Ich bevorzuge es aus zwei Gründen, Schutzblöcke einzusetzen, wo immer ich kann:
Im Allgemeinen bevorzuge ich Methoden, bei denen die Kernfunktionalität der Methode klar und minimal ist. Schutzblöcke helfen dabei, dies visuell umzusetzen.
quelle
Ich mag den "Fall Through" -Ansatz:
Die Aktion hat eine bestimmte Bedingung, alles andere ist nur die Standardrückgabe "fall through".
quelle
Wenn ich eine Single-If-Bedingung hätte, würde ich nicht zu viel Zeit damit verbringen, über den Stil nachzudenken. Aber wenn ich mehrere Schutzbedingungen habe, würde ich style2 vorziehen
Picuture dies. Angenommen, die Tests sind komplex und Sie möchten sie nicht wirklich in eine einzelne Bedingung mit ODER verknüpfen, um Komplexität zu vermeiden:
gegen
Hier gibt es zwei Hauptvorteile
Sie teilen den Code in einer einzigen Funktion in zwei visuell logische Blöcke auf: einen oberen Block mit Überprüfungen (Schutzbedingungen) und einen unteren Block mit ausführbarem Code.
Wenn Sie eine Bedingung hinzufügen / entfernen müssen, verringern Sie die Wahrscheinlichkeit, dass die gesamte if-elseif-else-Leiter durcheinander gebracht wird.
Ein weiterer kleiner Vorteil ist, dass Sie weniger Zahnspangensätze benötigen.
quelle
Das sollte eine Frage sein, die sich besser anhört.
drückt sich dann besser aus
Für kleine Methoden ist es kein großer Unterschied, aber für größere zusammengesetzte Methoden kann es schwieriger zu verstehen sein, da es nicht richtig getrennt werden kann
quelle
do something
eine Rücksendung beinhalten. Ist dies nicht der Fall, wird der zweite Codedo somethingelse
unabhängig vomif
Prädikat ausgeführt. Dies ist nicht die Funktionsweise des ersten Blocks.Ich finde Beispiel 1 irritierend, weil die fehlende return-Anweisung am Ende einer value-return-Funktion sofort das "Wait, there there something wrong" -Flag auslöst. In solchen Fällen würde ich also mit Beispiel 2 fortfahren.
In der Regel handelt es sich jedoch um mehr, je nach Zweck der Funktion, z. B. Fehlerbehandlung, Protokollierung usw. Ich bin also mit Lorand Kedves der Antwort auf diese Frage und habe am Ende in der Regel einen Ausstiegspunkt, auch auf Kosten einer zusätzlichen Flagvariablen. Dies erleichtert in den meisten Fällen die Wartung und spätere Erweiterungen.
quelle
Wenn Ihre
if
Anweisung immer zurückkehrt, gibt es keinen Grund, für den verbleibenden Code in der Funktion ein else zu verwenden. Dadurch werden zusätzliche Zeilen und zusätzliche Einrückungen hinzugefügt. Das Hinzufügen von unnötigem Code erschwert das Lesen, und wie jeder weiß, ist das Lesen von Code schwierig .quelle
In Ihrem Beispiel ist das
else
natürlich unnötig, ABER ...Wenn Sie schnell durch Codezeilen blättern, schauen Sie in der Regel auf die geschweiften Klammern und Einrückungen, um eine Vorstellung vom Code-Fluss zu erhalten. bevor sie sich tatsächlich auf den Code selbst festlegen. Wenn Sie also
else
den zweiten Codeblock mit geschweiften Klammern und Einrückungen versehen, kann der Leser schneller erkennen, dass es sich um eine A- oder B-Situation handelt, in der der eine oder der andere Block ausgeführt wird. Das heißt, der Leser sieht die geschweiften Klammern und Einrückungen, BEVOR sie diereturn
nach dem Anfangsbuchstaben sehenif
.Meiner Meinung nach ist dies einer der seltenen Fälle, in denen das Hinzufügen eines redundanten Codes die Lesbarkeit des Codes erhöht und nicht verringert.
quelle
Ich würde Beispiel 2 vorziehen, da es sofort offensichtlich ist, dass die Funktion etwas zurückgibt . Aber noch mehr, ich würde es vorziehen, von einem Ort zurückzukehren, so:
Mit diesem Stil kann ich:
Sieh sofort, dass ich etwas zurückgebe.
Fangen Sie das Ergebnis jedes Funktionsaufrufs mit nur einem Haltepunkt ab.
quelle
Mein persönlicher Stil tendiert dazu zu gehen
Verwenden Sie die auskommentierten
else
Anweisungen, um den Programmablauf anzuzeigen und lesbar zu halten. Vermeiden Sie jedoch massive Einrückungen, die bei vielen Schritten leicht über den Bildschirm gelangen können.quelle
else
Klauseln wäre, würde ich letzteren wählen, weil der Compiler sie auch effektiv ignorieren wird. Obwohl es auf den abhängen würdeelse if
nicht die Erhöhung der Vertiefung mehr als das Original einmal - wenn es tat würde ich Ihnen zustimmen. Aber meine Wahl wäre es, dieelse
komplett fallen zu lassen, wenn dieser Stil erlaubt wäre.ich würde schreiben
Ich bevorzuge diesen Stil, weil es am offensichtlichsten ist, dass ich zurückkehren würde
userName != null
.quelle
myString
Ergebnisse bekannt. Ich kopiere gerade die Funktion von OP. Ich werde es in etwas ändern, das realistischer aussieht. Boolescher Test ist trivial und sollte kein Problem sein.Meine Faustregel ist, entweder eine If-Return-Operation ohne Sonst (meistens für Fehler) oder eine vollständige If-else-If-Kette über alle Möglichkeiten durchzuführen.
Auf diese Weise vermeide ich es, zu ausgefeilt mit meiner Verzweigung umzugehen, da ich immer dann, wenn ich das tue, die Anwendungslogik in meine Ifs codiere, was die Pflege erschwert (z. B. wenn eine Aufzählung OK oder ERR ist und ich alle meine Ifs schreibe) Ausnutzen der Tatsache, dass! OK <-> ERR es nervt, dem Enum beim nächsten Mal eine dritte Option hinzuzufügen.)
In Ihrem Fall würde ich beispielsweise ein einfaches if verwenden, da "return if null" mit Sicherheit ein allgemeines Muster ist und Sie sich wahrscheinlich nicht um eine dritte Möglichkeit kümmern müssen (zusätzlich zu null / not null). in der Zukunft.
Wäre der Test jedoch etwas, das eine eingehendere Prüfung der Daten durchführt, würde ich mich stattdessen zu einem vollständigen Wenn-Andern irren.
quelle
Ich denke, es gibt eine Menge Fallstricke bei Beispiel 2, die später zu unbeabsichtigtem Code führen könnten. Zunächst einmal basiert der Fokus hier auf der Logik, die die Variable 'myString' umgibt. Aus diesem Grund sollten alle Tests von Bedingungen explizit in einem Codeblock durchgeführt werden, der bekannte und Standard- / unbekannte Logik berücksichtigt .
Was passiert, wenn später ungewollt Code in Beispiel 2 eingefügt wird, der die Ausgabe erheblich verändert hat?
Ich denke, mit dem
else
Block, der unmittelbar auf die Überprüfung auf eine Null folgt, hätten Programmierer, die die Erweiterungen für die zukünftigen Versionen hinzugefügt haben, die gesamte Logik zusammenaddiert, da wir jetzt eine Folge von Logik haben, die für die ursprüngliche Regel nicht beabsichtigt war (Rückgabe, wenn der Wert ist) Null).Ich bin fest davon überzeugt, dass einige der C # -Richtlinien zu Codeplex (Link dazu hier: http://csharpguidelines.codeplex.com/ ) Folgendes enthalten:
Msgstr "" "Fügen Sie einen beschreibenden Kommentar hinzu, wenn der Standardblock (else) leer sein soll. Wenn dieser Block nicht erreicht werden soll, lösen Sie eine InvalidOperationException aus, um zukünftige Änderungen zu erkennen, die durch die vorhandenen Fälle fallen könnten. Dies sorgt für besseren Code, weil Über alle Pfade, die der Code zurücklegen kann, wurde nachgedacht. "
Ich halte es für eine gute Programmierpraxis, bei Verwendung von Logikblöcken wie diesem immer einen Standardblock hinzuzufügen (if-else, case: default), um alle Codepfade explizit zu berücksichtigen und den Code keinen unbeabsichtigten logischen Konsequenzen auszusetzen.
quelle
myString
Wertes und der Code, der demif
Block folgt, ist die resultierende Logik, wenn der String! = Null ist. Da der Fokus auf der zusätzlichen Logik liegt, die diesen bestimmten Wert manipuliert, sollte er meines Erachtens in einemelse
Block gekapselt werden . Ansonsten eröffnet sich das Potenzial, wie ich gezeigt habe, die Logik ungewollt zu trennen und ungewollte Konsequenzen einzuführen. Könnte nicht die ganze Zeit passieren, aber das war wirklich eine Best-Practice- Frage.