Switch-Anweisung fällt in C # durch?

365

Das Durchfallen der Switch-Anweisung ist einer meiner persönlichen Hauptgründe für das Lieben switchgegenüber if/else ifKonstrukten. Ein Beispiel ist hier angebracht:

static string NumberToWords(int number)
{
    string[] numbers = new string[] 
        { "", "one", "two", "three", "four", "five", 
          "six", "seven", "eight", "nine" };
    string[] tens = new string[] 
        { "", "", "twenty", "thirty", "forty", "fifty", 
          "sixty", "seventy", "eighty", "ninety" };
    string[] teens = new string[]
        { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
          "sixteen", "seventeen", "eighteen", "nineteen" };

    string ans = "";
    switch (number.ToString().Length)
    {
        case 3:
            ans += string.Format("{0} hundred and ", numbers[number / 100]);
        case 2:
            int t = (number / 10) % 10;
            if (t == 1)
            {
                ans += teens[number % 10];
                break;
            }
            else if (t > 1)
                ans += string.Format("{0}-", tens[t]);
        case 1:
            int o = number % 10;
            ans += numbers[o];

            break;
        default:
            throw new ArgumentException("number");
    }
    return ans;
}

Die klugen Leute kriechen, weil das string[]s außerhalb der Funktion deklariert werden sollte: Nun , das ist nur ein Beispiel.

Der Compiler schlägt mit folgendem Fehler fehl:

Die Kontrolle kann nicht von einem Falletikett ('Fall 3:') zum anderen durchfallen
Die Kontrolle kann nicht von einem Falletikett ('Fall 2:') zum anderen durchfallen

Warum? Und gibt es eine Möglichkeit, diese Art von Verhalten zu erreichen, ohne drei ifSekunden zu haben?

Matthew Scharley
quelle

Antworten:

648

(Kopieren / Einfügen einer Antwort, die ich an anderer Stelle bereitgestellt habe )

Fallen durch switch- cases lassen sich durch keinen Code in einem erreicht werden case(siehe case 0) oder mit dem speziellen goto case(siehe case 1) oder goto default(siehe case 2) Formen:

switch (/*...*/) {
    case 0: // shares the exact same code as case 1
    case 1:
        // do something
        goto case 2;
    case 2:
        // do something else
        goto default;
    default:
        // do something entirely different
        break;
}
Alex Lyman
quelle
121
Ich denke, dass in diesem speziellen Fall goto nicht als schädlich angesehen wird.
Thomas Owens
78
Verdammt - ich programmiere seit den Anfängen von 1.0 mit C # und habe das bis jetzt noch nie gesehen. Nur um zu zeigen, lernst du jeden Tag neue Dinge.
Erik Forbes
37
Es ist alles gut, Erik. Der einzige Grund, warum ich davon wusste, ist, dass ich ein Compiler-Theorie-Nerd bin, der die ECMA-334-Spezifikationen mit einer Lupe liest.
Alex Lyman
13
@Dancrumb: Zum Zeitpunkt des Schreibens des Features hatte C # noch keine "weichen" Schlüsselwörter hinzugefügt (wie "Yield", "Var", "From" und "Select"), sodass drei echte Optionen zur Verfügung standen: 1 ) Machen Sie 'fallthrough' zu einem harten Schlüsselwort (Sie können es nicht als Variablennamen verwenden), 2) schreiben Sie den Code, der zur Unterstützung eines solchen weichen Schlüsselworts erforderlich ist, 3) verwenden Sie bereits reservierte Schlüsselwörter. # 1 war ein großes Problem für diese Portierungscodes; # 2 war eine ziemlich große technische Aufgabe, soweit ich weiß; und die Option, mit der sie sich entschieden haben, hatte # 3 einen Nebeneffekt: Andere Entwickler, die den Code lesen, nachdem die Tatsache aus dem Grundkonzept von goto
Alex Lyman
10
All dies spricht über neue / spezielle Schlüsselwörter für einen expliziten Fallthrough. Könnten sie nicht einfach das Schlüsselwort "continue" verwendet haben? Mit anderen Worten. Brechen Sie aus dem Schalter aus oder fahren Sie mit dem nächsten Fall fort (fallen Sie durch).
Tal Even-Tov
44

Das "Warum" besteht darin, ein versehentliches Durchfallen zu vermeiden, wofür ich dankbar bin. Dies ist eine nicht seltene Fehlerquelle in C und Java.

Die Problemumgehung besteht darin, goto zu verwenden, z

switch (number.ToString().Length)
{
    case 3:
        ans += string.Format("{0} hundred and ", numbers[number / 100]);
        goto case 2;
    case 2:
    // Etc
}

Das allgemeine Design des Schalters / Gehäuses ist meiner Ansicht nach etwas unglücklich. Es blieb zu nahe an C - es gibt einige nützliche Änderungen, die in Bezug auf den Umfang usw. vorgenommen werden könnten. Ein intelligenterer Schalter, der Musterabgleich usw. durchführen könnte, wäre wahrscheinlich hilfreich, aber das ändert sich wirklich von Schalter zu "Überprüfen einer Folge von Bedingungen". - an diesem Punkt würde vielleicht ein anderer Name verlangt.

Jon Skeet
quelle
1
Dies ist der Unterschied zwischen Schalter und if / elseif in meinem Kopf. Der Schalter dient zum Überprüfen verschiedener Zustände einer einzelnen Variablen, während if / elseif verwendet werden kann, um eine beliebige Anzahl von verbundenen Dingen zu überprüfen, jedoch nicht unbedingt eine einzelne oder dieselbe Variable.
Matthew Scharley
2
Wenn es ein versehentliches Durchfallen verhindern würde, wäre eine Compiler-Warnung meiner Meinung nach besser gewesen. Genau wie Sie eine haben, wenn Ihre if-Anweisung eine Aufgabe hat:if (result = true) { }
Tal Even-Tov
3
@ TalEven-Tov: Compiler-Warnungen sollten wirklich für Fälle gelten, in denen Sie den Code fast immer besser korrigieren können. Persönlich würde ich implizites Brechen bevorzugen, also wäre es zunächst kein Problem, aber das ist eine andere Sache.
Jon Skeet
26

Switch Fallthrough ist historisch gesehen eine der Hauptursachen für Fehler in moderner Software. Der Sprachdesigner hat beschlossen, das Springen am Ende des Falls obligatorisch zu machen, es sei denn, Sie gehen direkt ohne Verarbeitung direkt zum nächsten Fall über.

switch(value)
{
    case 1:// this is still legal
    case 2:
}
Münze
quelle
23
Ich verstehe nie, warum das nicht "Fall 1, 2:" ist
BCS
11
@ David Pfeffer: Ja, und so ist es auch case 1, 2:in Sprachen, die das erlauben. Was ich nie verstehen werde, ist, warum eine moderne Sprache dies nicht zulassen würde.
BCS
@BCS mit der goto-Anweisung können mehrere durch Kommas getrennte Optionen schwierig zu handhaben sein?
Pinguat
@pengut: Es könnte genauer sein zu sagen, dass case 1, 2:es sich um ein einzelnes Etikett mit mehreren Namen handelt. - FWIW, ich denke, die meisten Sprachen, die das Durchfallen verbieten, sind keine Sonderfälle für das Indium "aufeinanderfolgende Fallbezeichnungen", sondern behandeln die Fallbezeichnungen als Anmerkung zur nächsten Anweisung und erfordern die letzte Anweisung vor einer mit (eins oder) gekennzeichneten Anweisung mehr) Fallbezeichnungen als Sprung.
BCS
22

Um die Antworten hier zu ergänzen, denke ich, dass es sich lohnt, die entgegengesetzte Frage in Verbindung damit zu betrachten, nämlich. Warum hat C überhaupt einen Durchfall zugelassen?

Jede Programmiersprache dient natürlich zwei Zielen:

  1. Geben Sie dem Computer Anweisungen.
  2. Hinterlassen Sie eine Aufzeichnung der Absichten des Programmierers.

Die Schaffung einer Programmiersprache ist daher ein Gleichgewicht zwischen der Frage, wie diese beiden Ziele am besten erreicht werden können. Einerseits ist der Kompilierungs- oder Interpretationsprozess umso effizienter, zuverlässiger und zuverlässiger, je einfacher es ist, sich in Computeranweisungen umzuwandeln (unabhängig davon, ob es sich um Maschinencode, Bytecode wie IL handelt oder ob die Anweisungen bei der Ausführung interpretiert werden) kompakte Ausgabe. Im Extremfall führt dieses Ziel dazu, dass wir nur in Assembly, IL oder sogar in rohen Op-Codes schreiben, da die einfachste Kompilierung darin besteht, dass überhaupt keine Kompilierung erfolgt.

Umgekehrt ist das Programm sowohl beim Schreiben als auch während der Wartung verständlicher, je mehr die Sprache die Absicht des Programmierers zum Ausdruck bringt und nicht die Mittel, die zu diesem Zweck eingesetzt werden.

Jetzt switchhätte man es immer kompilieren können, indem man es in die äquivalente Kette von if-elseBlöcken oder ähnlichem konvertierte , aber es wurde so konzipiert, dass es die Kompilierung in ein bestimmtes gemeinsames Baugruppenmuster ermöglicht, in dem man einen Wert nimmt und einen Versatz daraus berechnet (sei es durch Nachschlagen einer Tabelle) indiziert durch einen perfekten Hash des Wertes oder durch tatsächliche Arithmetik des Wertes *). An dieser Stelle ist anzumerken, dass die C # -Kompilierung heute manchmal switchzum Äquivalent if-elsewird und manchmal einen Hash-basierten Sprungansatz verwendet (und ebenfalls mit C, C ++ und anderen Sprachen mit vergleichbarer Syntax).

In diesem Fall gibt es zwei gute Gründe, einen Durchfall zuzulassen:

  1. Es passiert sowieso nur natürlich: Wenn Sie eine Sprungtabelle in einen Befehlssatz einbauen und einer der früheren Befehlsstapel keine Art von Sprung oder Rückgabe enthält, wird die Ausführung natürlich auf den nächsten Stapel fortgesetzt. Fall-Through zuzulassen war das, was "einfach passieren" würde, wenn Sie das- switchusing C in eine Sprungtabelle verwandeln würden - unter Verwendung von Maschinencode.

  2. Codierer, die in Assembly geschrieben haben, waren bereits an das Äquivalent gewöhnt: Beim Schreiben einer Sprungtabelle von Hand in Assembly mussten sie berücksichtigen, ob ein bestimmter Codeblock mit einer Rückgabe, einem Sprung außerhalb der Tabelle enden oder einfach fortfahren würde zum nächsten Block. Daher war es auch breakfür den Codierer "natürlich" , wenn der Codierer bei Bedarf eine explizite Option hinzufügte .

Zu dieser Zeit war es daher ein vernünftiger Versuch, die beiden Ziele einer Computersprache in Einklang zu bringen, da sie sich sowohl auf den erzeugten Maschinencode als auch auf die Ausdruckskraft des Quellcodes bezieht.

Vier Jahrzehnte später sind die Dinge aus mehreren Gründen nicht ganz die gleichen:

  1. Codierer in C haben heute möglicherweise wenig oder keine Montageerfahrung. Codierer in vielen anderen Sprachen im C-Stil sind noch weniger wahrscheinlich (insbesondere Javascript!). Ein Konzept von "was Menschen von der Montage gewohnt sind" ist nicht mehr relevant.
  2. Verbesserungen bei den Optimierungen bedeuten, dass die Wahrscheinlichkeit höher ist, dass sie switchentweder umgesetzt werden, if-elseweil sie als der wahrscheinlich effizienteste Ansatz angesehen wurden, oder dass sie zu einer besonders esoterischen Variante des Sprungtabellenansatzes werden. Die Zuordnung zwischen den Ansätzen auf höherer und niedrigerer Ebene ist nicht mehr so ​​stark wie früher.
  3. Die Erfahrung hat gezeigt, dass Fall-Through eher der Minderheitsfall als die Norm ist (eine Studie des Sun-Compilers ergab, dass 3% der switchBlöcke einen anderen Fall-Through als mehrere Labels auf demselben Block verwendeten, und es wurde angenommen, dass die Verwendung von Fall hier bedeutete, dass diese 3% tatsächlich viel höher als normal waren). Die Sprache, wie sie studiert wird, macht das Ungewöhnliche leichter zugänglich als das Übliche.
  4. Die Erfahrung hat gezeigt, dass das Durchfallen sowohl in Fällen, in denen es versehentlich durchgeführt wird, als auch in Fällen, in denen jemand, der den Code verwaltet, den korrekten Durchfall übersieht, zu Problemen führt. Letzteres ist eine subtile Ergänzung zu den mit Fall-Through verbundenen Fehlern, denn selbst wenn Ihr Code vollkommen fehlerfrei ist, kann Ihr Fall-Through dennoch Probleme verursachen.

Beachten Sie im Zusammenhang mit diesen beiden letzten Punkten das folgende Zitat aus der aktuellen Ausgabe von K & R:

Das Durchfallen von einem Fall zum anderen ist nicht robust und neigt zum Zerfall, wenn das Programm geändert wird. Mit Ausnahme mehrerer Beschriftungen für eine einzelne Berechnung sollten Fall-Throughs sparsam verwendet und kommentiert werden.

Machen Sie aus gutem Grund nach dem letzten Fall eine Pause (hier die Standardeinstellung), obwohl dies logisch nicht erforderlich ist. Eines Tages, wenn am Ende ein weiterer Fall hinzugefügt wird, werden Sie durch diese defensive Programmierung gerettet.

Aus dem Maul des Pferdes ist ein Durchfall in C problematisch. Es wird als gute Praxis angesehen, Durchfälle immer mit Kommentaren zu dokumentieren. Dies ist eine Anwendung des allgemeinen Prinzips, dass man dokumentieren sollte, wo man etwas Ungewöhnliches tut, da dies die spätere Prüfung des Codes auslöst und / oder Ihren Code so aussehen lässt hat einen Anfängerfehler, wenn er tatsächlich korrekt ist.

Und wenn Sie darüber nachdenken, codieren Sie wie folgt:

switch(x)
{
  case 1:
   foo();
   /* FALLTHRU */
  case 2:
    bar();
    break;
}

Bin das Hinzufügen etwas den Durchfall explizit im Code zu machen, es ist einfach nicht etwas , das erkannt werden kann (oder deren Abwesenheit nachgewiesen werden kann) durch den Compiler.

Die Tatsache, dass on mit Fall-Through in C # explizit angegeben werden muss, bedeutet für Personen, die ohnehin gut in anderen C-Sprachen geschrieben haben, keine Strafe, da sie in ihren Fall-Throughs bereits explizit wären. †

Schließlich ist die Verwendung von gotohier bereits eine Norm aus C und anderen solchen Sprachen:

switch(x)
{
  case 0:
  case 1:
  case 2:
    foo();
    goto below_six;
  case 3:
    bar();
    goto below_six;
  case 4:
    baz();
    /* FALLTHRU */
  case 5:
  below_six:
    qux();
    break;
  default:
    quux();
}

In einem solchen Fall, in dem ein Block in den Code aufgenommen werden soll, der für einen anderen Wert als den ausgeführt wird, der einen zum vorhergehenden Block bringt, müssen wir ihn bereits verwenden goto. (Natürlich gibt es Mittel und Wege, dies mit unterschiedlichen Bedingungen zu vermeiden, aber das gilt für fast alles, was mit dieser Frage zu tun hat). Als solches baute C # auf der ohnehin normalen Art und Weise auf, mit einer Situation umzugehen, in der wir mehr als einen Codeblock in a treffen möchten switch, und verallgemeinerte ihn nur, um auch den Durchfall abzudecken. Es machte auch beide Fälle bequemer und selbstdokumentierender, da wir in C ein neues Etikett hinzufügen müssen, das caseaber in C # als Etikett verwenden können. In C # können wir das below_sixEtikett entfernen und verwenden, goto case 5was klarer ist, was wir tun. (Wir müssten auch hinzufügenbreakfür die default, die ich weggelassen habe, nur um den obigen C-Code eindeutig nicht C # -Code zu machen).

Zusammenfassend also:

  1. C # bezieht sich nicht mehr so ​​direkt auf die nicht optimierte Compilerausgabe wie C-Code vor 40 Jahren (und C heutzutage auch nicht mehr), was eine der Inspirationen für Fall-Through irrelevant macht.
  2. C # bleibt mit C kompatibel, da es nicht nur implizit ist break, sondern auch das Erlernen der Sprache durch Personen erleichtert, die mit ähnlichen Sprachen vertraut sind, und das Portieren erleichtert.
  3. C # entfernt eine mögliche Quelle von Fehlern oder missverstandenem Code, von dem in den letzten vier Jahrzehnten dokumentiert wurde, dass er Probleme verursacht.
  4. C # macht vorhandene Best Practices mit C (Document Fall Through) für den Compiler durchsetzbar.
  5. C # macht den ungewöhnlichen Fall zu dem mit expliziterem Code, den üblichen Fall zu dem mit dem Code, den man nur automatisch schreibt.
  6. C # verwendet den gleichen gotoAnsatz, um denselben Block von verschiedenen caseBezeichnungen zu treffen , wie er in C verwendet wird. Es verallgemeinert ihn nur auf einige andere Fälle.
  7. C # macht diesen gotobasierten Ansatz bequemer und klarer als in C, indem caseAnweisungen als Beschriftungen fungieren.

Alles in allem eine ziemlich vernünftige Designentscheidung


* Einige Formen von BASIC würden es einem ermöglichen, solche Dinge zu tun, GOTO (x AND 7) * 50 + 240die zwar spröde und daher ein besonders überzeugender Fall für ein Verbot sind goto, aber dazu dienen, ein höhersprachiges Äquivalent der Art und Weise zu zeigen, auf der Code auf niedrigerer Ebene einen Sprung basierend machen kann Arithmetik auf einen Wert, der viel vernünftiger ist, wenn er das Ergebnis einer Kompilierung ist, als etwas, das manuell gepflegt werden muss. Insbesondere Implementierungen von Duff's Device eignen sich gut für den entsprechenden Maschinencode oder IL, da jeder Anweisungsblock häufig dieselbe Länge hat, ohne dass nopFüllstoffe hinzugefügt werden müssen.

† Duffs Gerät wird hier als vernünftige Ausnahme wieder angezeigt. Die Tatsache, dass es mit diesem und ähnlichen Mustern zu einer Wiederholung von Operationen kommt, dient dazu, die Verwendung von Durchfall auch ohne einen expliziten Kommentar zu diesem Effekt relativ deutlich zu machen.

Jon Hanna
quelle
17

Sie können das Falletikett http://www.blackwasp.co.uk/CSharpGoto.aspx aufrufen

Die goto-Anweisung ist ein einfacher Befehl, der die Steuerung des Programms bedingungslos auf eine andere Anweisung überträgt. Der Befehl wird häufig kritisiert, da einige Entwickler befürworten, ihn aus allen höheren Programmiersprachen zu entfernen, da er zu Spaghetti-Code führen kann . Dies tritt auf, wenn es so viele goto-Anweisungen oder ähnliche Sprunganweisungen gibt, dass der Code schwer zu lesen und zu warten ist. Es gibt jedoch Programmierer, die darauf hinweisen, dass die goto-Anweisung bei sorgfältiger Verwendung eine elegante Lösung für einige Probleme bietet ...

kenny
quelle
8

Sie haben dieses Verhalten absichtlich ausgelassen, um zu vermeiden, dass es nicht vom Willen verwendet wurde, sondern Probleme verursachte.

Es kann nur verwendet werden, wenn der Fallteil keine Aussage enthält, wie z.

switch (whatever)
{
    case 1:
    case 2:
    case 3: boo; break;
}
Biri
quelle
4

Sie haben das Verhalten der switch-Anweisung (von C / Java / C ++) für c # geändert. Ich denke, die Begründung war, dass die Leute den Durchfall vergessen haben und Fehler verursacht wurden. Ein Buch, das ich gelesen habe, soll goto zum Simulieren verwenden, aber das klingt für mich nicht nach einer guten Lösung.

Ken
quelle
2
C # unterstützt goto, aber nicht fallthrough? Beeindruckend. Und es sind nicht nur diese. C # ist die einzige Sprache, von der ich weiß, dass sie sich so verhält.
Matthew Scharley
Anfangs hat es mir nicht gerade gefallen, aber "Fall-Thru" ist wirklich ein Rezept für eine Katastrophe (besonders unter Junior-Programmierern). Wie viele betont haben, erlaubt C # immer noch Fall-Thru für leere Zeilen (was die Mehrheit von ist Fälle.) "Kenny" hat einen Link gepostet, der die elegante Verwendung von Goto mit Switch-Case hervorhebt.
Brezel
Es ist meiner Meinung nach keine große Sache. 99% der Zeit möchte ich nicht durchfallen und bin in der Vergangenheit von Insekten verbrannt worden.
Ken
1
"Das klingt für mich nicht nach einer guten Lösung" - tut mir leid, das über Sie zu hören, denn dafür goto caseist es gedacht. Sein Vorteil gegenüber Fallthrough ist, dass es explizit ist. Dass einige Leute hier goto casenur Einwände erheben, zeigt, dass sie gegen "goto" indoktriniert wurden, ohne das Problem zu verstehen, und nicht in der Lage sind, selbstständig zu denken. Als Dijkstra "GOTO als schädlich" schrieb, sprach er Sprachen an, die keine andere Möglichkeit hatten, den Kontrollfluss zu ändern.
Jim Balter
@ JimBalter und wie viele Leute, die Dijkstra dazu zitieren, werden Knuth zitieren, dass "vorzeitige Optimierung die Wurzel allen Übels ist", obwohl dieses Zitat war, als Knuth explizit darüber schrieb, wie nützlich es sein gotokann, Code zu optimieren?
Jon Hanna
1

Sie können Fall Through wie C ++ mit dem Schlüsselwort goto erreichen.

EX:

switch(num)
{
   case 1:
      goto case 3;
   case 2:
      goto case 3;
   case 3:
      //do something
      break;
   case 4:
      //do something else
      break;
   case default:
      break;
}
Dai Tran
quelle
9
Wenn nur jemand das zwei Jahre zuvor gepostet hätte!
0

Nach jedem case-Block ist eine Sprunganweisung wie eine Unterbrechung erforderlich, einschließlich des letzten Blocks, unabhängig davon, ob es sich um eine case-Anweisung oder eine Standardanweisung handelt. Mit einer Ausnahme (im Gegensatz zur C ++ - switch-Anweisung) unterstützt C # keinen impliziten Durchfall von einer Fallbezeichnung zur anderen. Die einzige Ausnahme ist, wenn eine case-Anweisung keinen Code enthält.

- C # switch () Dokumentation

Powerlord
quelle
1
Mir ist klar, dass dieses Verhalten dokumentiert ist. Ich möchte wissen, WARUM es so ist, wie es ist, und welche Alternativen es gibt, um das alte Verhalten zu erreichen.
Matthew Scharley
0

Nach jeder case-Anweisung ist eine break- oder goto- Anweisung erforderlich , auch wenn es sich um einen Standardfall handelt.

Shilpa Gulati
quelle
2
Wenn nur jemand das zwei Jahre zuvor gepostet hätte!
1
@Poldie, es war das erste Mal lustig ... Shilpa, du brauchst nicht für jeden Fall eine Pause oder einen Goto, nur für jeden Fall mit einem eigenen Code. Sie können mehrere Fälle haben, die Code gut teilen.
Maverick
0

Nur eine kurze Anmerkung, um hinzuzufügen, dass der Compiler für Xamarin dies tatsächlich falsch verstanden hat und ein Durchfallen ermöglicht. Es wurde angeblich behoben, aber nicht veröffentlicht. Entdeckte dies in einem Code, der tatsächlich durchfiel und der Compiler beschwerte sich nicht.


quelle
0

Schalter (C # Referenz) sagt

C # erfordert das Ende der Schalterabschnitte, einschließlich des letzten.

Sie müssen also auch ein break;zu Ihrem defaultAbschnitt hinzufügen , da sonst immer noch ein Compilerfehler auftritt.

gm2008
quelle
Thx, das hat mir geholfen;)
CareTaker22
-1

C # unterstützt kein Durchfallen mit switch / case-Anweisungen. Ich weiß nicht warum, aber es gibt wirklich keine Unterstützung dafür. Verknüpfung

BKostenlos
quelle
Das ist so falsch. Siehe die anderen Antworten ... Der Effekt eines impliziten Durchfalls kann mit einem expliziten erzielt werdengoto case . Dies war eine absichtliche, kluge Designentscheidung der C # -Designer.
Jim Balter
-11

Sie haben vergessen, die "Pause" hinzuzufügen. Anweisung in Fall 3. In Fall 2 haben Sie sie in den if-Block geschrieben. Versuchen Sie deshalb Folgendes:

case 3:            
{
    ans += string.Format("{0} hundred and ", numbers[number / 100]);
    break;
}


case 2:            
{
    int t = (number / 10) % 10;            
    if (t == 1)            
    {                
        ans += teens[number % 10];                
    }            
    else if (t > 1)                
    {
        ans += string.Format("{0}-", tens[t]);        
    }
    break;
}

case 1:            
{
    int o = number % 10;            
    ans += numbers[o];            
    break;        
}

default:            
{
    throw new ArgumentException("number");
}
Marcus
quelle
2
Dies führt zu einer völlig falschen Ausgabe. Ich habe die switch-Anweisungen absichtlich weggelassen. Die Frage ist, warum der C # -Compiler dies als Fehler ansieht, wenn fast keine andere Sprache diese Einschränkung aufweist.
Matthew Scharley
5
Was für ein erstaunliches Versagen zu verstehen. Und Sie hatten 5 Jahre Zeit, dies zu löschen und haben es immer noch nicht getan? Verblüffend.
Jim Balter