Menu

C# switch Statement: case, break, default and Multiple Cases

How the C# switch statement works: switching on int, string, char and enum values, why every case needs break (error CS0163), stacking case labels for several values, goto case, default, string case sensitivity, and pattern case labels with when.

This page includes runnable editors - edit, run, and see output instantly.

A switch statement compares one value against a list of constant case labels and runs the section that matches. In C#, every section must end with break (or another statement that leaves it), so one case can never silently run into the next.

Output:

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

The value in parentheses is evaluated once and compared against each label. default runs when nothing matches; it is optional, and it may appear anywhere in the list, although it usually goes last. If there is no match and no default, the whole switch does nothing.

Every Section Needs a break

In C, C++, Java and JavaScript, forgetting break makes execution slide into the next case. C# turns that mistake into a compile error:

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;
}

The rule is that the end of a section's statement list must not be reachable. break is the usual way to satisfy it, but anything that leaves the section works:

  • return leaves the whole method, which is often the neatest form inside a small helper.
  • throw raises an exception for a value that should never occur.
  • continue jumps to the next iteration when the switch sits inside a loop.
  • goto case and goto default jump to another section on purpose.

The last section is not exempt. A default: at the bottom without break fails with CS8070, Control cannot fall out of switch from final case label ('default:').

Several Values in One Case

Labels with no statements between them share the section below them. This is the one kind of fall-through C# allows, because an empty label cannot hide any code:

Output:

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

Each section here ends with return, so no break is needed (a break after a return would be unreachable code). Two labels with the same value are an error, CS0152 The switch statement contains multiple cases with the label value '1', and every label must be a compile-time constant: a variable in a case fails with "a constant value is expected".

Switch on a String

Strings are the most common switch value after integers. The comparison is ordinal and case-sensitive, so normalize the input before switching:

Output:

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

Without ToLowerInvariant, "STOP" would reach default. A null value is legal to switch on: it matches no string constant and falls to default, so the switch itself never throws.

Switch on an Enum

Enums are what switch was made for: a closed set of named values.

Output:

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

The compiler does not check that a switch statement covers every enum member, and an enum variable can hold any integer of its underlying type ((OrderStatus)42 is legal). The default that throws turns a forgotten case into an immediate, obvious failure instead of a silent no-op.

goto case and goto default

When one case really should continue into another, C# makes you write the jump:

Output:

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

goto case takes a constant that must match one of the labels in the same switch. It is rare in real code: shared behavior is usually clearer as a method that several cases call. It is still the answer to "how do I fall through in C#".

Variables Inside Cases

The whole switch block is one scope, so two cases cannot declare a variable with the same name:

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;
}

Wrap each section's body in braces to give it its own scope: case "square": { int area = side * side; ... break; }.

break Inside a Loop

break in a case leaves the switch, not the loop around it. continue does the opposite: a switch is not a loop, so continue goes to the loop's next iteration.

Output:

end marker found
Total: 134

The loop kept going after "end" and added 99. To stop the loop from inside a switch, set a flag and test it after the switch, or move the loop into a method and return. The break and continue page compares the options.

Pattern Case Labels and when

Since C# 7.0, a case label can be a pattern instead of a constant: it can test the type of the value and add a when condition. This form is common in modern C# code:

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}";
    }
}

With patterns, order matters: the first matching case wins, and the compiler reports an error when a case can never be reached because an earlier one already covers it (putting case int n: above case int n when n < 0: fails). The when clause also works on constant cases: case 0 when isAdmin:. C# 9 added relational and logical patterns, so a case can read case >= 90: or case 'a' or 'e' or 'i':.

In C# 7 without patterns, the same type dispatch is an if chain with the is type pattern:

Output:

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

When every branch of a switch only computes a value, the switch expression is shorter still: var grade = score switch { >= 90 => "A", >= 80 => "B", _ => "C" };. The switch expression page covers its syntax, patterns and exhaustiveness rules.

What You Can Switch On

Value typeConstant casesNotes
int, long, byte and other integersyesthe classic case
charyescase 'a':
stringyesordinal, case-sensitive, null goes to default
boolyeslegal, but an if is clearer
any enumyesno exhaustiveness check
double, decimalfrom C# 7constants only; ranges need C# 9 relational patterns
any other typefrom C# 7through type patterns, case Circle c:

Frequently Asked Questions

Is break required in a C# switch?

Every case section must end in a statement that leaves it: usually break, but return, throw, continue (inside a loop) or goto case also count. Falling off the end of a section into the next one is a compile error, CS0163 Control cannot fall through from one case label ('case 1:') to another, and that includes the last section.

How do I handle multiple values in one C# switch case?

Stack the labels with nothing between them: case "sat": case "sun": Console.WriteLine("weekend"); break;. Empty case labels may fall through to the next label; only a section that contains statements must end in break. In C# 9 and later a pattern case can also say case 1 or 2 or 3:.

Is a C# switch on a string case sensitive?

Yes. String cases are compared with ordinal, case-sensitive equality, so "Yes" does not match case "yes":. Normalize the value first with switch (input.Trim().ToLowerInvariant()). A null string matches no constant case and goes to default.

Can a C# switch fall through like in C or Java?

Not implicitly. When you want one case to continue into another, say so with goto case <value>; or goto default;. This makes every fall-through visible in the code, which is why C# forbids the silent version.

What is the difference between a switch statement and a switch expression in C#?

A switch statement runs statements and needs case, break and default. A switch expression (C# 8 and later) produces a value: var label = n switch { 0 => "zero", > 0 => "positive", _ => "negative" };. Use the expression when every branch only computes a result.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED