Compiler error · error CS0163
Control cannot fall through from one case label to another
A case did its work and then… kept going into the next case. In C and C++ that's legal and caused decades of bugs; in C# the compiler simply refuses. Every non-empty case must end with break;, return;, or throw;.
See it happen
int d = 1;
switch (d)
{
case 1:
Console.WriteLine("one");
// no break — control would "fall through" into case 2
case 2:
Console.WriteLine("two");
break;
}
int d = 1;
switch (d)
{
case 1:
Console.WriteLine("one");
break; // hand control back — done
case 2:
Console.WriteLine("two");
break;
}
But you probably wanted stacked labels
The thing people usually mean when they "fall through" is several values sharing one body. That's legal — stack the labels with nothing between them:
void Classify(int day)
{
switch (day)
{
case 6:
case 7: // 6 and 7 share this body — no code between labels
Console.WriteLine("weekend");
break;
default:
Console.WriteLine("weekday");
break;
}
}
Classify(7);
Classify(3);
The rule is precise: empty labels may stack (fall-through of nothing); a label with any code must end the block itself.
Why C# is stricter than C++ — and why that's good
In C++, forgetting break silently executes the next case's code. The famous Apple goto fail bug was exactly this shape. C#'s designers made the missing break a compile-time error, trading a little convenience for the elimination of a whole bug class. When you hit CS0163, the compiler isn't nagging — it's the language keeping a 50-year-old trap shut.
Frequently asked
How do I fix error CS0163 in C#?
In C and C++ a missing break silently runs the next case — the shape of famous bugs like Apple's goto fail. C# makes it a compile error; empty stacked labels remain legal for shared bodies.
Why does C# forbid switch fall-through?
undefined
Endings the compiler accepts
int Apply(char op, int a, int b)
{
switch (op)
{
case '+':
return a + b; // return ends the case — no break needed
case '*':
return a * b;
default:
throw new Exception("unknown operator"); // throw ends it too
}
}
Console.WriteLine("result: " + Apply('*', 2, 4));
break exits the switch; return exits the whole method; throw exits explosively. Any of the three satisfies the rule — but plain "running off the end of a case" never will.
Checklist
- Every case with a body ends in
break;,return …;, orthrow …;. - Several values, one body → stack the labels, keep zero statements between them.
- Don't forget
default:— and it wants itsbreak;too. - Coming from C/C++/Java: yes, C# really is stricter — it's on purpose.