Mehrere Fälle in der switch-Anweisung

582

Gibt es eine Möglichkeit, mehrere Fallaussagen durchzugehen, ohne sie case value:wiederholt anzugeben ?

Ich weiß, dass das funktioniert:

switch (value)
{
   case 1:
   case 2:
   case 3:
      // Do some stuff
      break;
   case 4:
   case 5:
   case 6:
      // Do some different stuff
      break;
   default:
       // Default stuff
      break;
}

aber ich würde gerne so etwas machen:

switch (value)
{
   case 1,2,3:
      // Do something
      break;
   case 4,5,6:
      // Do something
      break;
   default:
      // Do the Default
      break;
}

Ist diese Syntax, an die ich denke, aus einer anderen Sprache oder fehlt mir etwas?

Das Ö
quelle
Gibt es einen Grund, warum Sie nicht nur eine IF-Anweisung verwenden (wenn Sie einen Bereich von Ints überprüfen)?
Eric Schoonover
2
ja charlse, der erste weg funktioniert gut, ich habe ihn an zahlreichen orten benutzt. Es ist schmutziger als ich möchte, aber es ist nützlich. Ich habe nur diese ganzen Zahlen als Beispiel verwendet. Die realen Daten waren vielfältiger. Ein if (1 || 2 || 3) {...} else if (4 || 5 || 6) {...} hätte auch funktioniert, aber es ist schwieriger zu lesen.
Theo
5
Warum halten Sie das letztere für schmutziger als das erstere? Letzteres fügt noch eine weitere Bedeutung hinzu ,, die mit keiner anderen Sprache im C-Stil geteilt wird. Das würde mir viel schmutziger erscheinen.
Jon Hanna
1
Möglicherweise haben Sie die Syntax des 2. von Ruby übernommen. So funktioniert es in dieser Sprache (obwohl der Wechsel unter anderem zum Fall wird und der Fall zum Fall wird)
juanpaco
4
Wichtiger Hinweis . Bereiche werden im Switch-Fall ab C # v7 unterstützt - Siehe Steve G.'s Antwort
RBT

Antworten:

313

Es gibt weder in C ++ noch in C # eine Syntax für die zweite Methode, die Sie erwähnt haben.

An Ihrer ersten Methode ist nichts auszusetzen. Wenn Sie jedoch sehr große Bereiche haben, verwenden Sie einfach eine Reihe von if-Anweisungen.

Brian R. Bondy
quelle
5
Als Ergänzung wollte ich einen Link zur C # -Sprachenspezifikation hinzufügen, die auf MSDN unter msdn.microsoft.com/en-us/vcsharp/aa336809.aspx verfügbar ist
Richard McGuire
Der Benutzer kann einige if's (oder eine Tabellensuche) verwenden, um die Eingabe auf eine Reihe von Aufzählungen zu reduzieren und die Aufzählung einzuschalten.
Harvey
5
wahrscheinlich ausgewählt, dass von VB.net
George Birbilis
1
VB.net ist besser für verschiedene case-Anweisungen geeignet ... außer dass sie nicht wie C # durchfallen. Nimm ein wenig, gib ein wenig.
Brain2000
Ich glaube das ist nicht mehr richtig. Siehe stackoverflow.com/questions/20147879/… . Auch auf genau
Dan Rayson
700

Ich denke, das wurde bereits beantwortet. Ich denke jedoch, dass Sie beide Optionen immer noch syntaktisch besser mischen können, indem Sie Folgendes tun:

switch (value)
{
    case 1: case 2: case 3:          
        // Do Something
        break;
    case 4: case 5: case 6: 
        // Do Something
        break;
    default:
        // Do Something
        break;
}
Carlos Quintanilla
quelle
3
'switch' sollte für c # in Kleinbuchstaben geschrieben werden?
Austin Harris
3
Der reduzierte Code wird auf das erste Beispiel in der Frage verlängert. Kann es auch so machen, wie es in der Frage steht.
MetalPhoenix
10
Warum die Mühe? Der automatische Eindringkörper in Visual Studio 2013 setzt diesen ohnehin auf das Format in der ursprünglichen Frage zurück.
Gustav
14
@T_D es wird unterstützt, weil es die Frage tatsächlich beantwortet. Das OP sagte, vermisse ich etwas ... Carlos antwortete mit dem, was ihm fehlte. Scheint mir ziemlich geschnitten und getrocknet zu sein. Hassen Sie nicht, dass er 422 positive Stimmen hat.
Mike Devenney
8
@MikeDevenney Dann haben Sie die Frage anders interpretiert, soweit ich sehe, wäre die richtige Antwort "Nein, c # hat keine Syntax dafür". Wenn jemand fragt "Ist es möglich, Flüssigkeit in ein Glas zu gießen, das ich verkehrt herum halte?" Die Antwort sollte "Nein" sein und nicht "Sie können Flüssigkeit aufgießen, wenn Sie sie verkehrt herum betrachten und Ihre Fantasie einsetzen", da es bei dieser Antwort nur um die Verwendung von Fantasie geht. Wenn Sie die reguläre Syntax verwenden, diese aber schlecht formatieren, sieht sie mit etwas Fantasie wie eine andere Syntax aus. Hoffentlich
verstehst
74

Diese Syntax stammt aus der Visual Basic Select ... Case-Anweisung :

Dim number As Integer = 8
Select Case number
    Case 1 To 5
        Debug.WriteLine("Between 1 and 5, inclusive")
        ' The following is the only Case clause that evaluates to True.
    Case 6, 7, 8
        Debug.WriteLine("Between 6 and 8, inclusive")
    Case Is < 1
        Debug.WriteLine("Equal to 9 or 10")
    Case Else
        Debug.WriteLine("Not between 1 and 10, inclusive")
End Select

Sie können diese Syntax nicht in C # verwenden. Stattdessen müssen Sie die Syntax aus Ihrem ersten Beispiel verwenden.

Neal
quelle
49
Dies ist eines der wenigen Dinge, die ich an * Basic vermisse.
Nickf
10
Hier haben wir eines der wenigen Displays, bei denen Visual Basic nicht so hässlich und vielseitiger als c # ist. Dies ist ein wertvolles Beispiel!
bgmCoder
Das ist ziemlich anständig. Ich frage mich, warum dies mit C # 8.0 nicht hinzugefügt wurde. Wäre ziemlich nett.
Sigex
69

In C # 7 (standardmäßig in Visual Studio 2017 / .NET Framework 4.6.2 verfügbar) ist eine bereichsbasierte Umschaltung jetzt mit der switch-Anweisung möglich und würde beim OP-Problem helfen.

Beispiel:

int i = 5;

switch (i)
{
    case int n when (n >= 7):
        Console.WriteLine($"I am 7 or above: {n}");
        break;

    case int n when (n >= 4 && n <= 6 ):
        Console.WriteLine($"I am between 4 and 6: {n}");
        break;

    case int n when (n <= 3):
        Console.WriteLine($"I am 3 or less: {n}");
        break;
}

// Output: I am between 4 and 6: 5

Anmerkungen:

  • Die Klammern (und )sind in der whenBedingung nicht erforderlich , werden jedoch in diesem Beispiel verwendet, um die Vergleiche hervorzuheben.
  • varkann auch anstelle von verwendet werden int. Zum Beispiel : case var n when n >= 7:.
Steve Gomez
quelle
3
Dies (Mustervergleich) sollte im Allgemeinen die beste Vorgehensweise sein, wenn Sie C # 7.x oder höher verwenden können, da dies viel klarer ist als die anderen Antworten.
UndyingJellyfish
Gibt es eine Möglichkeit, dies mit einer Liste von Aufzählungen zu erreichen? Wo sind die Enums int zugeordnet?
Sigex
33

Sie können die neue Zeile weglassen, die Ihnen Folgendes gibt:

case 1: case 2: case 3:
   break;

aber ich halte diesen schlechten Stil.

Allan Wind
quelle
20

.NET Framework 3.5 hat folgende Bereiche:

Enumerable.Range von MSDN

Sie können es mit "enthält" und der IF-Anweisung verwenden, da die SWITCH-Anweisung, wie jemand sagte, den Operator "==" verwendet.

Hier ein Beispiel:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

Aber ich denke, wir können mehr Spaß haben: Da Sie die Rückgabewerte nicht benötigen und diese Aktion keine Parameter akzeptiert, können Sie problemlos Aktionen verwenden!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

Das alte Beispiel mit dieser neuen Methode:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

Da Sie Aktionen und keine Werte übergeben, sollten Sie die Klammer weglassen. Dies ist sehr wichtig. Wenn Sie eine Funktion mit Argumenten benötigen, ändern Sie einfach den Typ von Actionin Action<ParameterType>. Wenn Sie Rückgabewerte benötigen, verwenden Sie Func<ParameterType, ReturnType>.

In C # 3.0 gibt es keine einfache Teilanwendung , um die Tatsache zu kapseln, dass der case-Parameter derselbe ist, aber Sie erstellen eine kleine Hilfsmethode (ein bisschen ausführlich, tho).

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

Hier ein Beispiel dafür, wie neue funktionale importierte Anweisungen meiner Meinung nach mächtiger und eleganter sind als die alte imperative.

Luca Molteni
quelle
3
Gute Wahl. Eine Sache zu beachten - Enumerable.Range hat Argumente int startund int count. Ihre Beispiele funktionieren nicht so, wie sie geschrieben wurden. Sie schreiben es so, als wäre das zweite Argument int end. Zum Beispiel - Enumerable.Range(11,20)würde zu 20 Zahlen führen, die mit 11 beginnen, und nicht zu Zahlen von 11 bis 20.
Gabriel McAdams
obwohl, wenn Sie mit einer Enum arbeiten, warum nicht so etwas? if (Enumerable.Range (MyEnum.A, MyEnum.M) {DoThing ();} else if (Enumerable.Range (MyEnum.N, MyEnum.Z) {DoAnotherThing ();}
David Hollowell - MSFT
4
Beachten Sie, dass dies Enumerable.Range(11,20).Contains(c)gleichbedeutend ist mit for(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;Wenn Sie eine große Reichweite hätten, würde es eine lange Zeit dauern, während Sie nur verwenden, >und <wäre schnell und konstant.
Jon Hanna
Eine Verbesserung: MySwitchWithEnumerableRückkehr voidist ein schwaches Design für diese Situation. GRUND: Sie haben eine if-elsein eine Reihe unabhängiger Anweisungen konvertiert - das verbirgt die Absicht, dass sie sich gegenseitig ausschließen - nur eine actionwird ausgeführt. Kehren Sie stattdessen boolmit body zurück. if (..) { action(); return true; } else return false;Die aufrufende Site zeigt dann die Absicht : if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));. Dies ist vorzuziehen. In diesem einfachen Fall ist dies jedoch keine wesentliche Verbesserung gegenüber Ihrer Originalversion mehr.
ToolmakerSteve
15

Hier ist die komplette C # 7-Lösung ...

switch (value)
{
   case var s when new[] { 1,2,3 }.Contains(s):
      // Do something
      break;
   case var s when new[] { 4,5,6 }.Contains(s):
      // Do something
      break;
   default:
      // Do the default
      break;
}

Es funktioniert auch mit Strings ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      // Do something
      break;
...
}
Carter Medlin
quelle
Dies würde bedeuten, dass Sie die Arrays jeder switch-Anweisung zuweisen, oder? Wäre es nicht besser, wenn wir sie als konstante Variablen hätten?
MaLiN2223
Elegant, aber es wäre in der Tat gut zu wissen, ob der Compiler dieses Szenario optimiert, damit wiederholte Aufrufe nicht jedes Mal den Overhead der Array-Konstruktion verursachen. Das Definieren der Arrays im Voraus ist eine Option, nimmt jedoch einen Großteil der Eleganz weg.
mklement0
11

Der folgende Code funktioniert nicht :

case 1 | 3 | 5:
// Not working do something

Der einzige Weg, dies zu tun, ist:

case 1: case 2: case 3:
// Do something
break;

Der Code, nach dem Sie suchen, funktioniert in Visual Basic, wo Sie problemlos Bereiche einfügen können. In der noneOption der switchAnweisung oder der if elseBlöcke, die praktisch sind, würde ich vorschlagen, im Extremfall .dll mit Visual Basic zu erstellen und zurück zu importieren zu Ihrem C # -Projekt.

Hinweis: Das Switch-Äquivalent in Visual Basic lautet Select Case.

keiner
quelle
7

Eine andere Möglichkeit wäre die Verwendung einer Routine. Wenn die Fälle 1 bis 3 alle dieselbe Logik ausführen, verpacken Sie diese Logik in eine Routine und rufen Sie sie für jeden Fall auf. Ich weiß, dass dies die case-Anweisungen nicht wirklich beseitigt, aber es implementiert einen guten Stil und hält die Wartung auf ein Minimum .....

[Bearbeiten] Alternative Implementierung hinzugefügt, um der ursprünglichen Frage zu entsprechen ... [/ Bearbeiten]

switch (x)
{
   case 1:
      DoSomething();
      break;
   case 2:
      DoSomething();
      break;
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}

Alt

switch (x)
{
   case 1:
   case 2:
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}
Dr8k
quelle
5

Eine weniger bekannte Facette des Schalters in C # ist, dass er vom Operator abhängt = und da er überschrieben werden kann, könnten Sie Folgendes haben:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}
Cyber ​​Oliveira
quelle
4
Dies könnte später zu einem großen Problem für jemanden werden, der versucht, den Code zu lesen
Andrew Harry
5

gcc implementiert eine Erweiterung der C-Sprache, um sequentielle Bereiche zu unterstützen:

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Bearbeiten : Ich habe gerade das C # -Tag auf der Frage bemerkt, daher hilft vermutlich eine gcc-Antwort nicht weiter.

DGentry
quelle
4

In C # 7 haben wir jetzt Pattern Matching, damit Sie Folgendes tun können:

switch (age)
{
  case 50:
    ageBlock = "the big five-oh";
    break;
  case var testAge when (new List<int>()
      { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge):
    ageBlock = "octogenarian";
    break;
  case var testAge when ((testAge >= 90) & (testAge <= 99)):
    ageBlock = "nonagenarian";
    break;
  case var testAge when (testAge >= 100):
    ageBlock = "centenarian";
    break;
  default:
    ageBlock = "just old";
    break;
}
Luke T O'Brien
quelle
3

Eigentlich mag ich den GOTO-Befehl auch nicht, aber er ist in offiziellen Microsoft-Materialien enthalten, und hier sind alle zulässigen Syntaxen.

Wenn der Endpunkt der Anweisungsliste eines Switch-Abschnitts erreichbar ist, tritt ein Fehler bei der Kompilierung auf. Dies ist als "No Fall Through" -Regel bekannt. Das Beispiel

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
default:
   CaseOthers();
   break;
}

ist gültig, da kein Schalterabschnitt einen erreichbaren Endpunkt hat. Im Gegensatz zu C und C ++ darf die Ausführung eines Switch-Abschnitts nicht zum nächsten Switch-Abschnitt und zum Beispiel "durchfallen"

switch (i) {
case 0:
   CaseZero();
case 1:
   CaseZeroOrOne();
default:
   CaseAny();
}

führt zu einem Fehler bei der Kompilierung. Wenn auf die Ausführung eines Switch-Abschnitts die Ausführung eines anderen Switch-Abschnitts folgen soll, muss ein expliziter goto-Fall oder eine goto-Standardanweisung verwendet werden:

switch (i) {
case 0:
   CaseZero();
   goto case 1;
case 1:
   CaseZeroOrOne();
   goto default;
default:
   CaseAny();
   break;
}

In einem Schalterabschnitt sind mehrere Beschriftungen zulässig. Das Beispiel

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
case 2:
default:
   CaseTwo();
   break;
}

Ich glaube, in diesem speziellen Fall kann das GOTO verwendet werden, und es ist tatsächlich der einzige Weg, durchzufallen.

Quelle: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx

Jiří Herník
quelle
Beachten Sie, dass dies in der Praxis gotofast immer vermieden werden kann (obwohl ich es hier nicht als "schrecklich" betrachte - es erfüllt eine bestimmte, strukturierte Rolle). In Ihrem Beispiel kann Fall 0 werden, da Sie die Fallkörper in Funktionen eingewickelt haben (eine gute Sache) CaseZero(); CaseZeroOrOne(); break;. Nicht gotoerforderlich.
ToolmakerSteve
Der Link ist halb unterbrochen (leitet weiter, "Visual Studio 2003 Retired Technical Documentation" ).
Peter Mortensen
2

Es scheint eine Menge Arbeit investiert worden zu sein, um Wege zu finden, wie eine der am wenigsten verwendeten C # -Syntaxen irgendwie besser aussehen oder besser funktionieren kann. Persönlich finde ich, dass die switch-Anweisung selten eine Verwendung wert ist. Ich würde dringend empfehlen, zu analysieren, welche Daten Sie testen und welche Endergebnisse Sie wünschen.

Angenommen, Sie möchten Werte in einem bekannten Bereich schnell testen, um festzustellen, ob es sich um Primzahlen handelt. Sie möchten vermeiden, dass Ihr Code die verschwenderischen Berechnungen durchführt, und Sie können eine Liste von Primzahlen in dem Bereich finden, den Sie online möchten. Sie können eine massive switch-Anweisung verwenden, um jeden Wert mit bekannten Primzahlen zu vergleichen.

Oder Sie können einfach eine Array-Karte mit Primzahlen erstellen und sofort Ergebnisse erzielen:

    bool[] Primes = new bool[] {
        false, false, true, true, false, true, false,    
        true, false, false, false, true, false, true,
        false,false,false,true,false,true,false};
    private void button1_Click(object sender, EventArgs e) {
        int Value = Convert.ToInt32(textBox1.Text);
        if ((Value >= 0) && (Value < Primes.Length)) {
            bool IsPrime = Primes[Value];
            textBox2.Text = IsPrime.ToString();
        }
    }

Vielleicht möchten Sie sehen, ob ein Zeichen in einer Zeichenfolge hexadezimal ist. Sie könnten eine ungly und etwas große switch-Anweisung verwenden.

Oder Sie können entweder reguläre Ausdrücke verwenden, um das Zeichen zu testen, oder die IndexOf-Funktion verwenden, um nach dem Zeichen in einer Zeichenfolge bekannter hexadezimaler Buchstaben zu suchen:

        private void textBox2_TextChanged(object sender, EventArgs e) {
        try {
            textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
        } catch {
        }
    }

Angenommen, Sie möchten eine von drei verschiedenen Aktionen ausführen, abhängig von einem Wert im Bereich von 1 bis 24. Ich würde vorschlagen, eine Reihe von IF-Anweisungen zu verwenden. Und wenn dies zu komplex wurde (oder die Zahlen größer waren, z. B. 5 verschiedene Aktionen, abhängig von einem Wert im Bereich von 1 bis 90), verwenden Sie eine Aufzählung, um die Aktionen zu definieren und eine Array-Karte der Aufzählungen zu erstellen. Der Wert wird dann verwendet, um in die Array-Map zu indizieren und die Aufzählung der gewünschten Aktion abzurufen. Verwenden Sie dann entweder eine kleine Menge von IF-Anweisungen oder eine sehr einfache switch-Anweisung, um den resultierenden Enum-Wert zu verarbeiten.

Das Schöne an einer Array-Map, die einen Wertebereich in Aktionen konvertiert, ist, dass sie leicht per Code geändert werden kann. Mit fest verdrahtetem Code können Sie das Verhalten zur Laufzeit nicht einfach ändern, aber mit einer Array-Map ist dies einfach.

Darin
quelle
Sie können auch Lambda-Ausdruck oder einen Delegierten
zuordnen
Gute Argumente. Ein kleiner Kommentar: Normalerweise fällt es mir leichter, eine Liste der Werte zu führen, die einem bestimmten Fall entsprechen, als eine Array-Map. Das Problem mit der Array-Karte ist, dass es leicht ist, einen Fehler zu machen. Anstelle der Primzahlen-Array-Map von true / falses können Sie beispielsweise einfach eine Liste von Primzahlen erstellen und diese zur Nachschlageleistung in ein HashSet laden. Selbst wenn es mehr als zwei Fälle gibt, ist normalerweise jeder Fall bis auf einen eine kleine Liste. Erstellen Sie daher entweder ein HashSet von Aufzählungen (falls spärlich) oder eine Array-Map im Code aus Listen der anderen Fälle.
ToolmakerSteve
1

Um die Konversation mit .NET 4.6.2 zu erweitern, konnte ich auch Folgendes tun. Ich habe den Code getestet und es hat bei mir funktioniert.

Sie können auch mehrere "ODER" -Anweisungen ausführen, wie unten:

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

Sie können auch überprüfen, ob es mit einem Wert in einem Array übereinstimmt:

            string[] statuses = { "text3", "text4", "text5"};

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when statuses.Contains(value):                        
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }
JeffS
quelle
Ist dies nicht abhängig von der C # -Version, nicht von der .NET-Version?
Peter Mortensen
1

Wenn Sie eine sehr große Anzahl von Zeichenfolgen (oder einen anderen Typ) haben, die alle dasselbe tun, empfehle ich die Verwendung einer Zeichenfolgenliste in Kombination mit der Eigenschaft string.Contains.

Wenn Sie also eine große switch-Anweisung wie diese haben:

switch (stringValue)
{
    case "cat":
    case "dog":
    case "string3":
    ...
    case "+1000 more string": // Too many string to write a case for all!
        // Do something;
    case "a lonely case"
        // Do something else;
    .
    .
    .
}

Vielleicht möchten Sie es durch eine ifAnweisung wie die folgende ersetzen :

// Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
// Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
    // Do something;
}
else
{
    // Then go back to a switch statement inside the else for the remaining cases if you really need to
}

Diese Skala eignet sich gut für eine beliebige Anzahl von Zeichenfolgenfällen.

Maxter
quelle
-5

Dazu würden Sie eine goto-Anweisung verwenden. Sowie:

    switch(value){
    case 1:
        goto case 3;
    case 2:
        goto case 3;
    case 3:
        DoCase123();
    //This would work too, but I'm not sure if it's slower
    case 4:
        goto case 5;
    case 5:
        goto case 6;
    case 6:
        goto case 7;
    case 7:
        DoCase4567();
    }
scone
quelle
7
@scone goto bricht ein grundlegendes Prinzip der prozeduralen Programmierung (von dem c ++ und c # noch verwurzelt sind; sie sind keine reinen OO-Sprachen (Gott sei Dank)). Die prozedurale Programmierung hat einen genau definierten Logikfluss, der durch Sprachkonstrukte und Methodenaufrufkonventionen bestimmt wird (wie der Laufzeitstapel wächst und schrumpft). Die goto-Anweisung umgeht diesen Fluss, indem sie im Grunde genommen willkürliches Herumspringen zulässt.
Samis
1
Ich sage nicht, dass es ein guter Stil ist, aber es macht das, wonach die ursprüngliche Frage gefragt hat.
Scone
2
Nein, es macht nicht "das, wonach die ursprüngliche Frage gefragt hat". Die ursprüngliche Frage hatte Code , der so funktionierte, wie er ist . Sie mussten es nicht reparieren. Und selbst wenn, ist dies ein schrecklicher Vorschlag. Es ist weniger prägnant und verwendet goto. Schlimmer noch, es ist eine völlig unnötige Verwendung goto, da die von OP angegebene ursprüngliche Syntax funktioniert. Die Frage war, ob es eine präzisere Möglichkeit gab, die alternativen Fälle anzugeben. Wie die Leute Jahre zuvor geantwortet haben , gibt es ja - wenn Sie bereit sind, die mehreren Fälle in eine Zeile zu setzen case 1: case 2:, und wenn der automatische Stil des Editors dies zulässt.
ToolmakerSteve
Der einzige Grund, warum Goto's als schlecht eingestuft werden, ist, dass es einigen Menschen schwer fällt, dem Logikfluss zu folgen. .Net MSIL (zusammengesetzter Objektcode) verwendet überall goto, weil es schnell ist, aber wenn .Net-Code ohne sie geschrieben werden kann und genauso performant ist, ist es besser, sie nicht zu verwenden, damit Sie nicht von Leuten wie @ geflammt werden Die herablassende Antwort von ToolmakerSteve.
Dynamiclynk
@wchoward - Bitte lesen Sie meine Antwort genauer durch. Meine Beschwerde betrifft nicht nur die Verwendung von goto . Ich habe Einwände erhoben, weil die Frage Code zeigte, der bereits so funktioniert, wie er ist , und diese Antwort a) diesen Arbeitscode nimmt und ihn ausführlicher und weniger gut strukturiert macht, ohne Nutzen , b) die Frage nicht beantwortet.
ToolmakerSteve