2010-09-02 34 views
8

1) Ich weiß, wie if…else if Anweisungen funktionieren, aber im nächsten Beispiel sind beide Methoden identisch, was den resultierenden Wert betrifft. Es spielt also eine Rolle, welche der beiden Methoden ich verwende oder sollte ich immer diejenige wählen, die dem Code, den der Code versucht, semantisch am nächsten kommt (hier vermute ich, dass die beiden Methoden semantisch recht unterschiedlich sind)? Also welche Methode würdest du benutzen und warum?Wann 'if ... else if' und wann zu verwenden ist

protected string GetNumberDescription(int value) 
{ 
    if (value >= veryBigNumber) 
     return veryBigNumberDescription; 
    else if (value >= bigNumber) 
     return bigNumberDescription; 
    else if (value >= smallNumber) 
     return smallNumberDescription; 
    else 
     return ""; 
} 

protected string GetNumberDescription(int value) 
{ 
    if (value >= veryBigNumber) 
     return veryBigNumberDescription; 
    if (value >= bigNumber) 
     return bigNumberDescription; 
    if (value >= smallNumber) 
     return smallNumberDescription; 
    else 
     return ""; 
} 

2) I losts Code bemerkt verwendet das folgende Format, wenn if ... else if Aussagen writting:

if ... 
else if ... 
else ... 

Aber ist das nicht (zumindest vom Konzept her) richtigere Weg:

if ... 
else 
    if ... 
    else ... 
+1

Ähnliche Fragen im Java-Kontext: http://StackOverflow.com/Questions/3579918/Programming-Preference-use-ELS-ifs-mit-Multiple-Reurn-Statements/ – BalusC

+1

Check-out http: //www.refactoring. com/catalog/replaceNestedConditionalWithGuardClauses.html ... –

+0

Die erste kann zu Problemen führen, wenn jemand eine else if-Anweisung irgendwo in den ifs-Block einfügt. Das Problem ist Code-Redundanz und Leistung erreicht – Woot4Moo

Antwort

16
  1. Sie sollten wahrscheinlich die erste verwenden. Es ist mehr akzeptiert und logischer. (Sie kümmern sich hinterher nicht um etwas, wenn diese Bedingung zutrifft ... geben Sie das in Ihrem Code an.)
  2. Es ist allgemein akzeptierter und kompakter und lesbarer, den ersten Weg zu benutzen (sonst wenn). Python hat sogar ein spezifisches Schlüsselwort dafür (elif).
+1

Die erste speichert keine unnötigen Auswertungen, da jede wahre Bedingung mit einer return-Anweisung endet. –

+0

@Michael La Voie - yup, Entschuldigung, ich hatte gerade meinen Fehler erkannt und korrigiert ... Ich habe nicht sofort die Rückgaben bemerkt – froadie

+0

vereinbart, der zweite Stil ist nur schlecht Codierung. –

7

Sie sind semantisch identisch. Ich bezweifle, dass es einen Unterschied in der Leistung gibt, also ist die Wahl über Stil und Lesbarkeit. Wenn Sie neugierig sind, kompilieren Sie den obigen Code in eine Assembly und verwenden Sie Reflector, um zu sehen, ob es einen Unterschied in der IL gibt. Meine Vermutung ist, es gäbe wenig Unterschied wenn überhaupt.

+0

Ich denke, das Poster erkennt, dass der generierte Code gleichwertig sein wird. Er fragt, ob es einen Grund gibt, einen * Codierungsstil * vor dem anderen zu bevorzugen. – Karmastan

+0

@Karmastan: Das OP sagt "semantisch sind sie ganz anders." Sie sind nicht semantisch verschieden. Ich habe keine starke Meinung über die stilistischen Unterschiede, nur darauf hingewiesen, dass sie dasselbe bedeuten. –

11
protected string GetNumberDescription(int value) 
{ 
    string ret = ""; 

    if (value >= veryBigNumber) 
     ret = veryBigNumberDescription; 
    else if (value >= bigNumber) 
     ret = bigNumberDescription; 
    else if (value >= smallNumber) 
     ret = smallNumberDescription; 

    return ret; 
} 

Die Frage ist schon beantwortet, aber ich habe dieses Bild, weil:

  1. Es Vorteile sind aus einer Funktion einen einzigen Ausgang zu haben.
  2. Die gleiche Variable wird wiederholt getestet, daher ist das if/elseif am besten geeignet.

Edited hinzufügen:

Ich bin normalerweise ein großer Fan von einer Funktion früh in Fällen wie diesem Austritt aus:

if (conditionOne) 
{ 
    if (conditionTwo) 
    { 
     if (conditionThree) 
     { 
      interesting_stuff(); 
     } 
    } 
    else 
     boring(); 
} 
return; 

Ich bin viel glücklicher sehen dies:

if (!conditionOne) 
    return; 

if (!conditionTwo) 
{ 
    boring(); 
    return; 
} 

if (!conditionThree) 
    return; 

interesting_stuff(); 
return; 

Aber wenn es Exits bei gibt viele verschiedene Verschachtelung Ebenen ist es zu leicht, einen zu verpassen, wenn Sie den Code lesen.

Auch, wie in den Kommentaren erwähnt: Ein einzelner Ausgang bedeutet nur einen Platz, um einen Haltepunkt zu setzen.

+0

Könnten Sie auf Ihren ersten Punkt erweitern? Normalerweise würde ich es lieber anders machen, um meinen Code kleiner zu machen. – Karmastan

+2

Da eine Rückgabe als Steuerflussanweisung fungiert, wird das Lesen des Codes komplexer. Wenn Sie in einem Funktionskörper alle return-Anweisungen gestreut haben, dann haben Sie mehr Verwendungsszenarien zum Nachdenken, wenn Sie versuchen zu verstehen, wie die Funktion funktioniert. Wenn Sie versuchen, die Funktion zu ändern und mehr Code hinzuzufügen, können Sie die Anweisungen nur dann am Anfang der Methode platzieren, wenn Sie sie immer ausführen möchten. Wenn Sie sie am Ende platzieren, wird die Anweisung in einigen Fällen gewonnen Geh nicht so weit. Aber vielleicht müssen Sie das Ergebnis analysieren, damit Sie es nicht am Anfang platzieren können. – AaronLS

+1

+1 Wir können einen einzelnen Punkt auf die einzelne Rückkehr setzen, um das Ergebnis zu überprüfen. – garik

6

Es ist vor allem eine Frage der Präferenz. Bei der Verwendung von return statements brauchen Sie meines Erachtens nicht die ellen, da klar ist, dass die Funktion genau dort endet. Es hängt alles sehr von der Situation und dem Stil ab, daher gibt es keinen klaren "besten" Weg, dies zu tun.

+0

+1 für die Aussage, dass die Situation/Stil abhängig ist - das ist die Art von Sache, über die sich Leute streiten, wenn beides akzeptabel ist. –

+0

Ich stimme einigermaßen zu. In diesem Fall sind die Bedingungen offensichtlich miteinander verknüpft und der else-if-Stil ist für Bugs defensiver, daher möchte ich sagen, dass dies weniger ein Stilproblem ist. – AaronLS

4

Ich würde die erste Option verwenden, wie es im Code zeigt die Vergleiche sind "gruppiert" einige. Für 2 glaube ich, dass sie in genau demselben IL-Code enden.

Ich stelle immer sicher, dass der häufigste Senario zuerst in der if..else-Anweisung ist, da dies für die Leistung am besten ist.

5

Ich würde ersteres vorschlagen, da Sie eine logische Wahl zwischen vier Möglichkeiten treffen. Sie gruppieren die Entscheidung in einem if/else if-Block.

Wenn Sie die Entscheidungen wie in Ihrer zweiten Funktion trennen, scheinen sie überhaupt nicht verbunden zu sein. Offensichtlich sind sie, wie die Wertvariable wiederholt wird, aber es muss nicht unbedingt offensichtlich sein.

Wenn Sie nichts zurückgeben müssen, geben Sie bitte null und keine leere Zeichenfolge zurück. In einer Anwendung, die ich pflege, ist es immer noch notwendig, if (Wert == null || value! = "") Zu verwenden.

+1

string.IsNullOrEmpty (Wert) :-) – Goblin

+0

Oh mein Gott, ich kann nicht glauben, dass ich nie gedacht hätte, dass diese Funktion Teil der Standardbibliothek wäre. Vielen Dank! –

13

ich persönlich würde

protected string GetNumberDescription(int value) 
    { 
     if (value >= veryBigNumber) 
      return veryBigNumberDescription; 
     if (value >= bigNumber) 
      return bigNumberDescription; 
     if (value >= smallNumber) 
      return smallNumberDescription; 
     return string.Empty; 
    } 

Es verwendet wirklich alles hängt davon ab, was Ihre Funktion tut. Wenn es so einfach ist, dann halte es einfach. Wenn Sie könnte etwas mit dem Ergebnis zu tun, bevor Sie es zurück, dann würde ich Egrunin Lösung

+0

für (Nummer: numberCollection) if (Wert> = number.value) return number.description; Wirf new IllegalArgumentException(); ---- was dann offensichtlich eine Methode sein sollte, die innerhalb deiner NumberCollection-Klasse existiert und dies wird numberCollection.getDescription (value); Haben Sie keine Angst, gut zu kodieren. (Ich unterstelle nicht, dass die Antwort für Lehrzwecke nicht klarer/besser war, nur den nächsten Schritt zu machen) Auch Nummer ist eines dieser Wörter, die, wenn Sie es zu oft hintereinander tippen, es nicht richtig aussehen. –

4

1) Die erste ist weiter verbreitet und in gängige Praxis verwenden. Es wäre also ratsam, sich an die Standardpraxis zu halten. Im Allgemeinen

2), wenn wir mehr als eine bedingte Anweisung haben, else if wird in den Zwischen bedingten Ausgaben verwendet und sonst in den letzten bedingten Ausgaben verwendet wird. Außerdem könnte es effizienter sein, da ich glaube, dass es nicht jedes Mal die gleiche Bedingung überprüfen muss, im Gegensatz zu dem if-else-if-else ... Typ.

Es ist mehr wie eine Wahl, die Ihnen zur Verfügung gestellt wird, wo Sie Ihre eigenen aus vielen Pfaden finden, die zum selben Bestimmungsort gehen. Aber die Wahl, die Sie oft hören oder sehen, ist die, die aufgrund der Erfahrung vieler Benutzer und Experten beliebt ist.

10

Wenn die Bedingungen sich gegenseitig ausschließen, dann denke ich ein anderes wenn Muster am besten ist. Es wird schwieriger, versehentlich zu brechen, wenn sich der Code entwickelt und komplexer wird, weil Ihr Kontrollfluss die gegenseitige Exklusivität der Logik genauer repräsentiert.

Überlegen Sie, ob jemand Ihr erstes Beispiel-einkalkuliert sind solche egrunin dem Beispiel ähnlich zu sein, dass es nur eine Rückkehr ist, aber bedenken Sie vergaßen sie die „anders“ zu jedem wenn hinzuzufügen:

protected string GetNumberDescription(int value) 
{ 
    string ret = ""; 

    if (value >= veryBigNumber) 
     ret = veryBigNumberDescription; 
    if (value >= bigNumber) 
     ret = bigNumberDescription; 
    if (value >= smallNumber) 
     ret = smallNumberDescription; 
    // BUG: very big numbers still fall through to this last condition, 
    //   because they meet all conditions 

    return ret; 
} 

Sie haben habe gerade einen Fehler eingeführt. Sie haben vielleicht nicht erkannt, dass die Renditen Teil der ausgedrückten Logik waren. Während der Fehler hier offensichtlich ist, könnte dieser Code ein paar Jahre später tatsächlich komplexer, langwieriger und schwieriger zu lesen sein, so dass es einfacher ist, einen solchen Fehler zu machen.

Nachweis unerwartete Bug

Außerdem, wenn mindestens eine Bedingung erfüllt sein muß (dh niemals einen leeren String zurück), dann würde ich eine Ausnahme in den letzten sonst werfen, wenn Sie auf alle Fälle gehen davon aus sollte behandelt werden. Dies würde einen Fehler im Code erkennen, bei dem der Code durch alle Elemente fiel und keine übereinstimmende Bedingung gefunden wurde. Wenn Sie keine Ausnahme auslösen, kann der Fehler seltsames Verhalten verursachen. Wie behandelt der Rest des Codes die nicht initialisierte leere Zeichenfolge? Hängt stark vom Code ab.Die Idee, eine Ausnahme auszulösen, besteht darin, einen Fehler genau dort zu verursachen, wo der Fehler liegt, so dass er leicht identifiziert und korrigiert werden kann, anstatt zuzulassen, dass die Anwendung mit einer ungültigen Rückgabe weiterläuft.

if (value >= smallNumber) 
    ret = smallNumberDescription; 
else if(...) 
    ret = otherNumberDescription; 
else 
    throw new InvalidOperationException($"No condition matched for value={value}"); 

return ret; 

Wenn mit entsprechender Ausnahme Protokollierung/notifications gepaart, dann würde dies ermöglicht es Ihnen bewusst, diesen Fehler zu werden und eine Bedingung in den unerwarteten Werte zu behandeln. Nicht wirklich notwendig für sehr einfache Bedingungen, aber sehr hilfreich beim proaktiven Finden und Korrigieren von Fehlern in dieser Art von Code.

+1

Dies ist die richtige Antwort auf die Frage, die das OP gestellt hat. –

4

Die Alternativen sind semantisch ziemlich nah, also spielt es keine Rolle. Wie in einigen Antworten vorgeschlagen, kann das Ergebnis in einer String-Variablen und am Ende zurückgegeben werden, um besser darzustellen, was Sie in der Methode tun.

Eine weitere Alternative ist den bedingten Operanden zu verwenden, die Ihnen einen weniger ausführlichen Code gibt:

protected string GetNumberDescription(int value) { 
    return 
    value >= veryBigNumber ? veryBigNumberDescription : 
    value >= bigNumber ? bigNumberDescription : 
    value >= smallNumber ? smallNumberDescription : 
    String.Empty; 
} 
+0

Ich denke, das ist schwerer zu verstehen. –

+0

@Daniel Moura: Warum? – Guffa

+0

Ich muss daran denken, diesen Code zu verstehen. Vielleicht bin ich es nicht gewohnt, diesen Stil zu sehen. Wenn ich ... sonst wenn ... sonst verstehe ich sofort, ich muss nicht darüber nachdenken. Ich benutze und sehe Code wie diesen a> b? c: d und ich denke, ist in Ordnung. Wenn ich den bedingten Operanden verschachtele, ist es schwieriger, herauszufinden, was passiert. –

4

Mit den return Aussagen, es spielt wirklich keine Rolle. Ich stimme überhaupt nicht mit denen überein, die sagen, dass der zweite in irgendeiner Weise schlimmer ist. Was macht es schlimmer?

Als Antwort auf Ihre zweite Frage: Sie haben Recht. In der Tat sind nicht nur die beiden Arten der Formatierung if/else ifeffektiv das gleiche; sie sind tatsächlich buchstäblich das gleiche. C# erzwingt keine bestimmte Formatierung Stil, so sind diese alle identisch:

// This... 
if (A()) 
    return "Congrats!"; 
else if (B()) 
    return "Not bad!"; 
else if (C()) 
    return "Next time..."; 
else 
    return "Uh-oh."; 

// ...is the same as this... 
if (A()) 
    return "Congrats!"; 
else 
    if (B()) 
     return "Not bad!"; 
    else 
     if (C()) 
      return "Next time..."; 
     else 
      return "Uh-oh."; 

// ...which is the same as this... 
if (A()) return "Congrats!"; else 
         if    (B()) 
      return "Not bad!"; 


else 
{ if 
(C()) 


    return 


"Next time...";else{ 
return "Oh-oh."; 
}} 
4
protected string GetNumberDescription(int value) 
{ 
    return new NumberDescriptor(value).toString(); 
} 

Alles was Sie brauchen ist Ihre Logik zu verstecken. Nimm das nicht zu ernst, aber ... ich würde es so machen. Ich weiß, deine Frage ist hier nicht beantwortet, aber es gibt schon genug wenn/dann/else Beispiele in diesem Thema.

3

Ich würde sagen, die erste zu verwenden, wenn die Funktion als eine von vier Möglichkeiten zurückgegeben wird, die alle als "erfolgreich" betrachtet werden. Ich würde den letzteren Stil verwenden, wenn einige Rückgaben als "Fehler" bezeichnet werden. Zum Beispiel (Spielzeug Beispiel - werfen könnte für die Fehlerfälle besser):

 
string get_suit_name(int suit) 
{ 
    string suit_names[4] = {"clubs", "diamonds", "hearts", "spades"}; 

    if (0 > suit) /* Avoid LT sign */ 
    return "Suit is improperly negative!"; 
    if (suit >= 4) 
    return "Suit is too big!"; 
    return suit_names[suit]; 
} 
3

Nun aus meiner Sicht wäre es diese Prioritäten vom höchsten zum niedrigsten sein.

Funktionalität/das Endziel Reduzierung der Kosten in jedem Bereich/Niveau zu erreichen Ablesbarkeit

^^^^ beachten Sie, dass viele dieser auf meiner Liste bestreiten wird und die Lesbarkeit über eine Verringerung der Kosten nennen, es hängt wirklich von Ihre Arbeit envi. und das Endziel, aber ich finde das am häufigsten. Aber rate mal von einem Rookie, der nicht viel bedeutet huh: D

Danach ist es ziemlich viele Erdnüsse. Gleiches gilt für? : Operator. Wenn Sie überzeugt sind, dass es besser lesbar ist, sollten Sie es tun. Funktional ist es nicht wirklich wichtig. Aber wenn() {} else {} unterscheidet sich deutlich von if() {} else if() {} Also wähle, was der optimale Code ist (Höchste gewünschte Ergebnisse minus unerwartete Ergebnisse - 0,5 * Lesbarkeits-Score) so ziemlich, was ich gehen würde auf.

Jetzt, da der Code das gleiche für Sie tut, kommt ein neues Attribut ins Spiel, wird dieser Code zu einem späteren Zeitpunkt bearbeitet? Und wenn ja, was wäre dann am besten? Vergiss nicht die Zukunft des Codes, noch die Kommentare, dass ein Gratisbonus mit dabei ist.Sie können sogar beides tun, wenn Sie es nicht für die Zeit herausfinden und nur den anderen kommentieren, aber das hinterlässt schlampige Textwände, die später bei der Säuberung/Veröffentlichung entfernt werden.

3

Für das Beispiel vorgesehen ist, brauchen Sie nicht zu befürchten „wenn“ Aussagen, wenn Sie bereit sind, eine Tonne Lesbarkeit zu opfern und möglicherweise ein wenig Geschwindigkeit:

string [] descriptions = {"", smallNumberDescription, bigNumberDescription, veryBigNumberDescription}; 

protected string GetNumberDescription(int value) 
{ 
    int index = Convert.ToInt32(value >= smallNumber) + Convert.ToInt32(value >= bigNumber) 
       + Convert.ToInt32(value >= veryBigNumber); 
    return descriptions[index]; 
} 
3

In Bezug auf Leistung, Sie können je nach Compiler/Interpreter gleich sein. Meiner Meinung nach ist der zweite besser .... viel einfacher zu debuggen.

5

Sie möchten "else if" verwenden, da das nur ausgelöst wird, wenn das erste "if" nicht akzeptiert wird. In Ihrem Fall sind die 3 if-Anweisungen in Ordnung, einfach weil, wenn ein letzter "if" korrekt ist, dann die vorherigen "if" s nicht sein können.

In einem Fall, in dem alle Ihre if-Anweisungen korrekt sein könnten, möchten Sie andernfalls if verwenden.

Beispiel:

if (8<10) { 
return 10; 
} 
if (8<9) { 
return 9; 
} 

, dass ein sehr einfaches Beispiel ist, aber Sie bekommen die Idee. Sie verwenden "else if", wenn nur eine "if" -Anweisung ausgelöst werden soll.

1

Nun, in Ihrem Fall, ich würde das vorschlagen:

protected string GetNumberDescription(int value) { 
    if (value >= veryBigNumber) 
     return veryBigNumberDescription; 
    if (value >= bigNumber) 
     return bigNumberDescription; 
    if (value >= smallNumber) 
     return smallNumberDescription; 

    return ""; 

}

Da Sie von der Funktion auf einem der wahren Zustand zurückkehrt, gibt es keine Notwendigkeit zu verwenden " sonst, wenn '. Im Allgemeinen wird "else if" verwendet, wenn sich die beiden Bedingungen nicht gegenseitig ausschließen, was hier nicht der Fall ist. In diesem Fall wird der Code nicht weiter ausgeführt, wenn eine der Bedingungen zutrifft. Auch die letzte 'else' ist nicht erforderlich, denn die Steuerung erreicht diesen Punkt nur, wenn alle oben genannten Bedingungen falsch sind.

Es hängt alles davon ab, wo Sie es verwenden und wie. Das Hauptmotiv ist, die Lesbarkeit Ihres Codes zu maximieren und ihn so elegant und leicht verständlich wie möglich zu gestalten.