it-swarm-eu.dev

Soll ich switch-Anweisungen verwenden oder long, wenn ... sonst Ketten?

Wenn ich von der switch-Anweisung höre, wird sie oft verschoben, um lange if ... else-Ketten zu ersetzen. Aber es scheint, dass ich, wenn ich die switch-Anweisung verwende, mehr Code schreibe, als ich sonst schreiben würde, wenn ... sonst. Sie haben auch andere Probleme wie alle Variablen für alle Aufrufe im selben Bereich halten .

Hier ist ein Code, der den Fluss darstellt, den ich normalerweise schreibe ( dank diam )

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

if (which == 0) {
    comment = "You look so much better than usual.";
} else if (which == 1) {
    comment = "Your work is up to its usual standards.";
} else if (which == 2) {
    comment = "You're quite competent for so little experience.";
} else {
    comment = "Oops -- something is wrong with this code.";
}

Dann wollen sie, dass ich das durch Folgendes ersetze:

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

switch (which) {
    case 0:  
             comment = "You look so much better than usual.";
    break;
    case 1:  
             comment = "Your work is up to its usual standards.";
    break;
    case 2:  
             comment = "You're quite competent for so little experience.";
    break;
    default: 
             comment = "Oops -- something is wrong with this code.";
}

Scheint viel mehr Code in einer viel umständlicheren Syntax zu sein. Aber hat die Verwendung der switch-Anweisung wirklich einen Vorteil?

36
TheLQ

Für diese besondere Situation scheint es mir, dass sowohl if als auch case schlechte Entscheidungen sind. Ich würde ein einfaches Array verwenden:

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

Als Randnotiz sollten Sie den Multiplikator im Allgemeinen basierend auf der Größe des Arrays berechnen, anstatt den 3 Hart zu codieren.

Wenn Sie würden einen Fall/Schalter verwenden, besteht der Unterschied zu einer Kaskade von if -Anweisungen (oder mindestens einem Hauptunterschied) darin, dass switch semi- kann Automatische Optimierung basierend auf der Anzahl und Dichte der Werte, während eine Kaskade von if -Anweisungen dem Compiler keine andere Wahl lässt, als Code so zu generieren, wie Sie ihn geschrieben haben, und einen Wert nach dem anderen zu testen, bis eine Übereinstimmung gefunden wird. Mit nur drei realen Fällen ist das kaum ein Problem, aber mit einer ausreichenden Anzahl kann/könnte es signifikant sein.

57
Jerry Coffin

Das Problem mit dem if...else if... Kette ist, dass ich, wenn ich zum Lesen komme, jede einzelne if Bedingung betrachten muss, um zu verstehen, was das Programm tut. Zum Beispiel könnten Sie so etwas haben:

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(Für eine kleine Anzahl solcher Aussagen ist es natürlich nicht so schlimm)

Ich hätte keine Möglichkeit zu wissen, dass Sie die Bedingungsvariable zur Hälfte geändert haben, ohne jede einzelne Anweisung zu lesen. Da ein switch Sie jedoch nur auf eine einzige Bedingungsvariable beschränkt, kann ich auf einen Blick sehen, was passiert.

Am Ende des Tages würde ich jedoch weder switch noch eine Kette von if...else if. Oft ist eine bessere Lösung eine Art Sprungtabelle oder Wörterbuch für Fälle wie in der ursprünglichen Frage oder Polymorphismus (wenn Ihre Sprache dies unterstützt). Das ist natürlich nicht immer möglich, aber ich würde nach einer Lösung suchen, die switch als ersten Schritt vermeidet ...

23
Dean Harding
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

Die obige Art, diese Art von Schaltergehäuse zu schreiben, ist ziemlich üblich. Der Grund, warum Sie den Schalterfall als sperriger empfanden, ist, dass Ihr Körper nur aus einer Zeile bestand und Sie bei einem Schalterfall auch die break-Anweisung benötigten. Das Schaltergehäuse hatte also die doppelte Körpergröße wie sonst. Bei umfangreicherem Code wird die break-Anweisung dem Text nicht viel hinzufügen. Für einzeilige Textkörper ist es üblich, den Code in dieselbe Zeile wie die case-Anweisung zu schreiben.

Wie bereits erwähnt, macht ein Switch-Fall die Absicht klarer. Sie möchten eine Entscheidung treffen, die auf dem Wert einer einzelnen Variablen/eines einzelnen Ausdrucks basiert. Meine Kommentare sind rein lesbar und nicht leistungsbasiert.

14
aufather

In diesem Fall entspricht die switch-Anweisung deutlicher der Absicht des Codes: Wählen Sie eine Aktion aus, die auf einem einzelnen Wert basiert.

Die if-Aussagen hingegen sind viel schwerer zu lesen - Sie müssen sich alle ansehen, um sicherzugehen, was los ist. Für mich ist es weniger Code (auch wenn die Anzahl der Zeichen kann etwas höher sein), da es weniger gibt, um mental zu analysieren.

8
FinnNk

Ich stimme Jerry zu, dass eine Reihe von Zeichenfolgen für diesen speziellen Fall besser ist, aber dass es im Allgemeinen besser ist, eine switch/case-Anweisung als eine Kette von elseifs zu verwenden. Es ist einfacher zu lesen, und manchmal kann der Compiler auf diese Weise besser optimieren, aber es gibt noch einen weiteren Vorteil: Es ist verdammt viel einfacher zu debuggen.

Wenn Sie diesen Schalter drücken, müssen Sie nur einmal einen Schritt machen, um auf dem richtigen Ast zu landen, anstatt mehrere if-Anweisungen gleichzeitig sorgfältig zu durchlaufen und möglicherweise die Taste zu schnell zu drücken und daran vorbeizukommen und etwas zu verpassen und zu haben von vorn anfangen.

8
Mason Wheeler

Ich bevorzuge Schalter in solchen Fällen, es passt viel besser zum Punkt des Codes, führen Sie eine andere Anweisung für jeden unterschiedlichen Eingabewert aus. Das if..else wirkt eher wie ein "Trick", um den gleichen Effekt zu erzielen.

switch Anweisungen sind auch sauberer, es ist leicht, einen Tippfehler in all diesen ==

Bei großen Blöcken in C ist der Wechsel außerdem schneller.

else..if kann besser geeignet sein, wenn Sie so etwas wie Bereiche haben (zwischen 1 und 100, tun Sie dies, zwischen 100 und 200 tun Sie das) oder in C, wenn Sie versuchen, mit Elementen wie Zeichenfolgen zu wechseln (was in anderen Sprachen möglich ist ). Welches ist das gleiche.

Ich neige dazu, viele Schalter zu verwenden, wenn ich in C programmiere.

3
Khelben

Ich mag im Allgemeinen keinen Ansatz. Langer Wechsel oder wenn Anweisungen nur darum gebeten werden, in eine objektorientierte Abstraktion umgestaltet zu werden (jedoch würde ich Ihr Beispiel als kurz und nicht lang klassifizieren).

Ich würde diese Art von Code persönlich in eine separate Hilfsmethode einbinden.

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

Wenn Sie den Schalter in eine separate Methode einfügen, können Sie return-Anweisungen direkt in die switch-Anweisung einfügen (zumindest in c #), sodass auch keine break-Anweisungen erforderlich sind und der Code viel einfacher zu lesen ist.

Und das ist imho viel schöner als der if/else if/else if-Ansatz.

2
Pete

Wählen Sie etwas aus, das effizient und knapp ist, und dann Dokument nicht nur, was Sie getan haben, sondern warum.

Code kann überarbeitet werden und nicht immer vom ursprünglichen Autor.

Es gibt Zeiten, in denen Sie absichtlich eine Implementierung einer anderen vorziehen weil Sie denken über Code nach, der nicht existiert.

2

Eines der Dinge, die den C/C # -Stil switch besonders nervig machen, ist das Beharren darauf, dass der Wert case Literale sind. Eine schöne Sache an VB/VB.NET ist, dass select/case erlaubt, dass jeder Fall ein beliebiger boolescher Ausdruck ist. Das ist bequem. Sofern eine Reihe sich gegenseitig ausschließender boolescher Ausdrücke oft hilfreich ist, ist eine Reihe von if/else ifs flexibler, ganz zu schweigen davon, dass sie effizienter zu tippen und zu lesen sind.

0
Joel Brown

In Python gibt es keine switch-Anweisung, denn wenn/Elif/else Nice ist:

a = 5

if a==1:
    print "do this"
Elif a == 2:
    print "do that"
Elif a == 3:
    print "do the other"
Elif 3 < a < 9:
    print "do more"
Elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

Einfach richtig?

0