Menu

C# switch-Anweisung: case, break, default und mehrere Fälle

Wie die switch-Anweisung in C# funktioniert: switch auf int-, string-, char- und enum-Werte, warum jeder case ein break braucht (Fehler CS0163), case-Labels für mehrere Werte stapeln, goto case, default, Groß- und Kleinschreibung bei Strings und case-Labels mit Mustern und when.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Eine switch-Anweisung vergleicht einen Wert mit einer Liste konstanter case-Labels und führt den passenden Abschnitt aus. In C# muss jeder Abschnitt mit break enden (oder mit einer anderen Anweisung, die ihn verlässt), ein Fall kann also nie stillschweigend in den nächsten laufen.

Ausgabe:

200: OK
302: redirect
404: not found
500: unhandled status

Der Wert in Klammern wird einmal ausgewertet und mit jedem Label verglichen. default läuft, wenn nichts passt; es ist optional und darf überall in der Liste stehen, steht aber meist am Ende. Gibt es keinen Treffer und kein default, tut der ganze switch nichts.

Jeder Abschnitt braucht ein break

In C, C++, Java und JavaScript läuft die Ausführung bei vergessenem break in den nächsten Fall. C# macht aus diesem Fehler einen Kompilierfehler:

switch (level)
{
    case 1:
        Console.WriteLine("read");
        // error CS0163: Control cannot fall through from one case label ('case 1:') to another
    case 2:
        Console.WriteLine("write");
        break;
}

Die Regel lautet: Das Ende der Anweisungsliste eines Abschnitts darf nicht erreichbar sein. break ist der übliche Weg, das zu erfüllen, aber alles, was den Abschnitt verlässt, funktioniert:

  • return verlässt die ganze Methode, oft die sauberste Form in einer kleinen Hilfsmethode.
  • throw löst eine Exception für einen Wert aus, der nie vorkommen sollte.
  • continue springt zum nächsten Durchlauf, wenn der switch in einer Schleife steht.
  • goto case und goto default springen absichtlich in einen anderen Abschnitt.

Der letzte Abschnitt ist nicht ausgenommen. Ein default: am Ende ohne break scheitert mit CS8070, Control cannot fall out of switch from final case label ('default:').

Mehrere Werte in einem case

Labels ohne Anweisungen dazwischen teilen sich den Abschnitt darunter. Das ist die einzige Art des Durchfallens, die C# erlaubt, weil ein leeres Label keinen Code verstecken kann:

Ausgabe:

'O' is a vowel
'k' is a consonant or symbol
' ' is a space
'7' is a digit

Jeder Abschnitt endet hier mit return, also ist kein break nötig (ein break nach einem return wäre unerreichbarer Code). Zwei Labels mit demselben Wert sind ein Fehler, CS0152 The switch statement contains multiple cases with the label value '1', und jedes Label muss eine Konstante zur Kompilierzeit sein: Eine Variable in einem case scheitert mit „a constant value is expected“.

switch auf einen String

Nach Ganzzahlen sind Strings der häufigste switch-Wert. Der Vergleich ist ordinal und beachtet Groß- und Kleinschreibung, normalisiere die Eingabe also vor dem switch:

Ausgabe:

Starting the server
Stopping the server
Server is running
Unknown command: restart
Unknown command: (none)

Ohne ToLowerInvariant würde "STOP" bei default landen. Ein null-Wert ist als switch-Wert erlaubt: Er passt auf keine String-Konstante und fällt zu default, der switch selbst wirft also nie.

switch auf ein Enum

Genau dafür wurde switch gemacht: eine geschlossene Menge benannter Werte.

Ausgabe:

Pending: wait for payment
Paid: pack and ship
Shipped: track the parcel
Delivered: nothing, order is closed
Cancelled: nothing, order is closed
ArgumentOutOfRangeException for value 42

Der Compiler prüft nicht, ob eine switch-Anweisung jedes Enum-Member abdeckt, und eine Enum-Variable kann jede Ganzzahl ihres zugrunde liegenden Typs enthalten ((OrderStatus)42 ist erlaubt). Das default, das wirft, macht aus einem vergessenen Fall einen sofortigen, offensichtlichen Fehler statt einer stillen Nichtaktion.

goto case und goto default

Wenn ein Fall wirklich in einen anderen übergehen soll, lässt C# dich den Sprung ausschreiben:

Ausgabe:

admin:
  manage users
  edit posts
  read posts
editor:
  edit posts
  read posts
guest:
  read posts

goto case nimmt eine Konstante, die auf eines der Labels im selben switch passen muss. In echtem Code ist es selten: Gemeinsames Verhalten ist meist als Methode klarer, die mehrere Fälle aufrufen. Trotzdem ist es die Antwort auf „wie falle ich in C# durch“.

Variablen in Fällen

Der ganze switch-Block ist ein einziger Gültigkeitsbereich, zwei Fälle können also keine Variable mit demselben Namen deklarieren:

switch (shape)
{
    case "square":
        int area = side * side;
        break;
    case "rectangle":
        int area = width * height;   // error CS0128: A local variable or function named 'area' is already defined in this scope
        break;
}

Setze den Rumpf jedes Abschnitts in geschweifte Klammern, um ihm einen eigenen Gültigkeitsbereich zu geben: case "square": { int area = side * side; ... break; }.

break in einer Schleife

break in einem case verlässt den switch, nicht die Schleife drumherum. continue tut das Gegenteil: Ein switch ist keine Schleife, also springt continue zum nächsten Durchlauf der Schleife.

Ausgabe:

end marker found
Total: 134

Die Schleife lief nach "end" weiter und addierte 99. Um die Schleife aus einem switch heraus zu beenden, setze ein Flag und prüfe es nach dem switch, oder verschiebe die Schleife in eine Methode und nutze return. Die Seite zu break und continue vergleicht die Optionen.

case-Labels mit Mustern und when

Seit C# 7.0 kann ein case-Label statt einer Konstante ein Muster sein: Es kann den Typ des Werts prüfen und eine when-Bedingung ergänzen. Diese Form ist in modernem C#-Code verbreitet:

static string Describe(object value)
{
    switch (value)
    {
        case null:
            return "nothing";
        case int n when n < 0:
            return $"negative int {n}";
        case int n:
            return $"int {n}";
        case string s when s.Length == 0:
            return "empty string";
        case string s:
            return $"string \"{s}\"";
        default:
            return $"other: {value.GetType().Name}";
    }
}

Bei Mustern zählt die Reihenfolge: Der erste passende Fall gewinnt, und der Compiler meldet einen Fehler, wenn ein Fall nie erreicht werden kann, weil ein früherer ihn schon abdeckt (case int n: über case int n when n < 0: zu setzen scheitert). Die when-Klausel funktioniert auch bei konstanten Fällen: case 0 when isAdmin:. C# 9 hat relationale und logische Muster hinzugefügt, ein case kann also case >= 90: oder case 'a' or 'e' or 'i': lauten.

In C# 7 ohne Muster ist dieselbe Unterscheidung nach Typ eine if-Kette mit dem is-Typmuster:

Ausgabe:

negative int -3
int 12
empty string
string "hi"
other: Decimal
nothing

Wenn jeder Zweig eines switch nur einen Wert berechnet, ist der switch-Ausdruck noch kürzer: var grade = score switch { >= 90 => "A", >= 80 => "B", _ => "C" };. Die Seite zum switch-Ausdruck behandelt seine Syntax, Muster und die Regeln zur Vollständigkeit.

Worauf du switchen kannst

WerttypKonstante FälleHinweise
int, long, byte und andere Ganzzahlenjader klassische Fall
charjacase 'a':
stringjaordinal, beachtet Schreibweise, null geht zu default
booljaerlaubt, aber ein if ist klarer
jedes enumjakeine Prüfung auf Vollständigkeit
double, decimalab C# 7nur Konstanten; Bereiche brauchen relationale Muster aus C# 9
jeder andere Typab C# 7über Typmuster, case Circle c:

Häufig gestellte Fragen

Ist break in einem C#-switch Pflicht?

Jeder case-Abschnitt muss mit einer Anweisung enden, die ihn verlässt: meist break, aber auch return, throw, continue (in einer Schleife) oder goto case zählen. Vom Ende eines Abschnitts in den nächsten zu fallen ist ein Kompilierfehler, CS0163 Control cannot fall through from one case label ('case 1:') to another, und das gilt auch für den letzten Abschnitt.

Wie behandle ich in C# mehrere Werte in einem switch-case?

Stapele die Labels ohne etwas dazwischen: case "sat": case "sun": Console.WriteLine("weekend"); break;. Leere case-Labels dürfen zum nächsten Label durchfallen; nur ein Abschnitt mit Anweisungen muss mit break enden. Ab C# 9 kann ein Muster-case auch case 1 or 2 or 3: lauten.

Beachtet ein C#-switch auf einen String Groß- und Kleinschreibung?

Ja. String-Fälle werden ordinal und mit Beachtung der Schreibweise verglichen, "Yes" passt also nicht auf case "yes":. Normalisiere den Wert vorher mit switch (input.Trim().ToLowerInvariant()). Ein null-String passt auf keinen konstanten Fall und landet bei default.

Kann ein C#-switch durchfallen wie in C oder Java?

Nicht implizit. Wenn ein Fall in einen anderen übergehen soll, sag es mit goto case <value>; oder goto default;. So ist jedes Durchfallen im Code sichtbar, und deshalb verbietet C# die stille Variante.

Was ist der Unterschied zwischen einer switch-Anweisung und einem switch-Ausdruck in C#?

Eine switch-Anweisung führt Anweisungen aus und braucht case, break und default. Ein switch-Ausdruck (ab C# 8) erzeugt einen Wert: var label = n switch { 0 => "zero", > 0 => "positive", _ => "negative" };. Nimm den Ausdruck, wenn jeder Zweig nur ein Ergebnis berechnet.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S