779 Stimmen

Sollte eine Funktion nur eine Rückgabeanweisung haben?

Gibt es gute Gründe, warum es besser ist, nur eine Rückgabeanweisung in einer Funktion zu haben?

Oder ist es in Ordnung, aus einer Funktion zurückzukehren, sobald dies logisch korrekt ist, d.h. es kann viele Return-Anweisungen in der Funktion geben?

25 Stimmen

Ich stimme nicht zu, dass die Frage sprachenfeindlich ist. Bei einigen Sprachen ist die Mehrfachrückgabe natürlicher und bequemer als bei anderen. Ich würde mich eher über frühe Rückgaben in einer C-Funktion beschweren als in einer C++-Funktion, die RAII verwendet.

3 Stimmen

Diese Frage ist eng damit verbunden und enthält ausgezeichnete Antworten: programmers.stackexchange.com/questions/118703/

0 Stimmen

Sprachunabhängig? Erklären Sie jemandem, der eine funktionale Sprache verwendet, dass er einen Return pro Funktion verwenden muss :p

9voto

David Clarke Punkte 12420

Ich neige dazu, Guard-Klauseln zu verwenden, um früh zurückzukehren und ansonsten am Ende einer Methode zu beenden. Die Regel des einmaligen Ein- und Ausstiegs hat historische Bedeutung und war besonders hilfreich, als es um alten Code ging, der für eine einzige C++-Methode mit mehreren Rückgaben (und vielen Fehlern) 10 A4-Seiten umfasste. In jüngerer Zeit hat es sich bewährt, die Methoden klein zu halten, so dass mehrere Ausgänge weniger ein Hindernis für das Verständnis darstellen. In dem folgenden Kronoz-Beispiel, das wir oben kopiert haben, geht es um die Frage, was in //Rest des Codes... ?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

Ich weiß, dass das Beispiel etwas konstruiert ist, aber ich wäre versucht, die foreach Schleife in eine LINQ-Anweisung, die dann als Schutzklausel betrachtet werden könnte. Auch hier ist die Absicht des Codes in einem erfundenen Beispiel nicht ersichtlich und someFunction() kann eine andere Nebenwirkung haben oder das Ergebnis kann in der Praxis verwendet werden. // Rest des Codes... .

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

Geben Sie die folgende überarbeitete Funktion:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}

0 Stimmen

Gibt es in C++ keine Ausnahmen? Warum würden Sie dann null anstatt eine Ausnahme zu machen, die anzeigt, dass das Argument nicht akzeptiert wird?

1 Stimmen

Wie ich bereits angedeutet habe, ist der Beispielcode aus einer früheren Antwort kopiert ( stackoverflow.com/a/36729/132599 ). Das ursprüngliche Beispiel gab Nullen zurück, und die Umstrukturierung zum Auslösen von Argumentausnahmen war für den Punkt, den ich zu machen versuchte, oder für die ursprüngliche Frage nicht wesentlich. Als eine Frage der guten Praxis, dann ja würde ich normalerweise (in C#) werfen ein ArgumentNullException in einer guard-Klausel statt einen Nullwert zurück.

7voto

OysterD Punkte 6480

Ein guter Grund, den ich mir vorstellen kann, ist die Wartung des Codes: Sie haben einen einzigen Ausgangspunkt. Wenn Sie das Format des Ergebnisses ändern wollen,..., ist es einfach viel einfacher zu implementieren. Außerdem kann man zum Debuggen dort einfach einen Haltepunkt setzen :)

Abgesehen davon musste ich einmal in einer Bibliothek arbeiten, in der die Codierungsstandards "eine Rückgabeanweisung pro Funktion" vorschrieben, und ich fand das ziemlich schwierig. Ich schreibe viel Code für numerische Berechnungen, und da gibt es oft "Sonderfälle", so dass der Code am Ende ziemlich schwer zu folgen war...

0 Stimmen

Das macht keinen wirklichen Unterschied. Wenn Sie den Typ der lokalen Variable, die zurückgegeben wird, ändern, müssen Sie alle Zuweisungen an diese lokale Variable korrigieren. Und es ist wahrscheinlich ohnehin besser, eine Methode mit einer anderen Signatur zu definieren, da Sie dann auch alle Methodenaufrufe ändern müssen.

0 Stimmen

@MaartenBodewes-owlstead - Es kann einen Unterschied machen. Um nur zwei Beispiele zu nennen, wo Sie no alle Zuweisungen an die lokale Variable korrigieren oder die Methodenaufrufe ändern müssen, könnte die Funktion ein Datum als String zurückgeben (die lokale Variable wäre ein tatsächliches Datum, das erst im letzten Moment als String formatiert wird), oder sie könnte eine Dezimalzahl zurückgeben und Sie möchten die Anzahl der Dezimalstellen ändern.

0 Stimmen

@nnnnnn OK, wenn Sie die Ausgabe nachbearbeiten wollen... Aber ich würde einfach eine neue Methode erstellen, die die Nachbearbeitung vornimmt, und die alte Methode in Ruhe lassen. Das ist nur leicht schwieriger zu refaktorisieren, aber Sie müssen ohnehin prüfen, ob die anderen Aufrufe mit dem neuen Format kompatibel sind. Aber es ist dennoch ein triftiger Grund.

7voto

Jon Limjap Punkte 92084

Mehrere Exit-Points sind in Ordnung, wenn die Funktion klein genug ist, d. h. wenn sie auf einem Bildschirm in ihrer Gesamtheit betrachtet werden kann. Wenn eine längere Funktion ebenfalls mehrere Exit-Points enthält, ist das ein Zeichen dafür, dass die Funktion weiter zerlegt werden kann.

Deshalb vermeide ich Funktionen mit mehreren Ausgängen sofern nicht unbedingt erforderlich . Ich habe den Schmerz von Fehlern gespürt, die auf eine verirrte Rückkehr in einer obskuren Zeile in komplexeren Funktionen zurückzuführen sind.

6voto

ima Punkte 7865

Ein einziger Exit-Point macht den Code - unter sonst gleichen Bedingungen - deutlich lesbarer. Aber es gibt einen Haken: beliebte Konstruktion

resulttype res;
if if if...
return res;

ist eine Fälschung, "res=" ist nicht viel besser als "return". Es hat eine einzige Return-Anweisung, aber mehrere Punkte, an denen die Funktion tatsächlich endet.

Wenn Sie eine Funktion mit mehreren Rückgaben (oder "res="s) haben, ist es oft eine gute Idee, sie in mehrere kleinere Funktionen mit einem einzigen Exit-Point zu unterteilen.

6voto

Phil Bennett Punkte 4733

Ich habe mit schrecklichen Codierungsstandards gearbeitet, die einem einen einzigen Ausstiegspfad aufzwangen, und das Ergebnis ist fast immer unstrukturiertes Spaghetti, wenn die Funktion alles andere als trivial ist - am Ende hat man viele Unterbrechungen und Fortsetzungen, die einfach im Weg sind.

0 Stimmen

Ganz zu schweigen davon, dass Sie Ihrem Verstand sagen müssen, dass er die if Anweisung vor jedem Methodenaufruf, der erfolgreich ist oder nicht :(

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X