What’s with those “break” statements?

One comment from my recent post was big enough to handle separately...

Thomas wrote:

I'll second the break statement. Why is it really necessary? Haven't you guys got enough feedback to acknowledge that wasn't the brightest move? You say it is there to please the C++ developers, because they are your main target.

  1. The C++ developers thought they were smart. You just stated they aren't, as you don't believe they can adjust to the new rules.
  2. You insult all the other programmers, as they are not the target. At least not more than a minor target.
  3. Finally, you insult everyone not on the C# team, as you think you are smarter than us. You could just have made the break statement optional.

When we were designing the language, we decided we wanted to do something about the fall-through behavior of C++. In my years of writing C and C++ code, I had come across several cases where the behavior was troublesome. I believe that experience was widely shared among the language designers.

So, we decided that any fallthrough would have to be explicit through a "goto" statement, which has the nice byproduct that cases can be re-ordered without a problem. We then had to decided whether "break" would be required, or whether it would be optional.

We decided to make it explicit to make it easier for developers who write in more than one language - which our research data shows to be a significant percentage of developers. The question is not whether we think C# developers are smart enough to learn the new rules - the question is whether we wanted to force developers to remember two different kinds of switch statements so that they could save 7 characters of typing. Changing the syntax there would have been a gratuitious change. With this behavior, while there are different rules for *writing* switch statements, reading them is the same across languages.

Having written code both in C# and C++ recently, I'm happy with the choice that we made. There are enough differences between the two languages that I'm happy not to have another to deal with.

I admit that we haven't done the best job at explaining our language rationale. But now that you know the rationale behind this decision, do you think it was the right one?

Comments (24)

  1. ShadowChaser says:

    I don’t think it was the right decision (sorry). I understand the rationale behind it, but one of the major appeals of C# is that it was designed from scratch to "make sense".

    It’s the first language I’ve used that is, for the most part, consistently designed from start to finish – everything makes sense, has a purpose, and coaxes the developer toward writing bug-free code.

    The "break" statement requirement in a switch is a small exception. It does not "match" the rest the design of the C# language. It’s kind of like requiring developers to place "return;" at the bottom of every function that returns "void".

    The break statement in C# had it’s purpose – so that C++ developers would not accidentally write bugs into their code. Now that C# is more mature, perhaps it is no longer as much of an issue.

    It doesn’t bother me having it there, but I can’t help but thinking about it every time I type it in a case statement 🙂

  2. William Robertson says:

    I always wondered why you didn’t allow fall through switch statements. I still don’t buy it though. Having break required switch syntax has taken away some of the power and simplicity I liked with C++. It is usually and easy bug to fix, but you learn it pretty quick how it works. Plus it is more explicit that way.

    But now I don’t complain as much. I learned to workaround the limitation of the language! <smirk>

  3. Shital Shah says:

    I think this is the weiredest reason I heard for a design of a futuristic modern language. Because research data shows current statistics of two language developers? Shouldn’t it rather be driven by logic and purity and beauty and such stuff? I guess before C# came out in betas, there were *no* developers really using anyway to generate any convincing statistics! I always see people justifieng legacy overheads by puting statistics on table. C’mon, give us a break! (may be not)

  4. Chris Nahr says:

    C# was hardly intended to be "futuristic"… quite the opposite, it’s supposed to look familiar to C++ and Java users.

    Anyway, I don’t mind the break statement, and I agree that C/C++ case fall-through is an atrocious misfeature of these languages, but I do think a redesign of the switch/case statement would have been better.

    That is: Redefine the case statement so that it is followed by only a single statement or block, just like for/foreach/if/else.

    The rest would remain the same. No fall-through, you can use "goto case-label", but if you want more than one statement after a case you have to use a { } block.

    Then switch/case would behave like any other control statement, rather than like goto’s redheaded bastard child. Besides, you have to use curly braces anyway if you need local variables in a case block.

  5. AT says:

    I like the way C# solved this problem.

    Savings of 6 characters is not very big deal.

    But this will make it clear that this source code does:

    int x = 1;

    switch(x) {

    case 1: A();

    case 2: B();


    I dislike the way others propose here – make this source code behavior a language specific.

    In C++ it will call both methods, but in C# only one? No way. It looks like people here never developed in two languages in same day. This is very trivial to forget that language you are now coding and add bugs in source code (you need to search then).

    Something I dislike – that we need to write

    case 2:

    case 3:

    case 4:

    instead of single

    case 2,3,4:

    This is break contract created by break/goto. He you get fallthrough – but it’s banned in other scenario.

    Even more – I dislike that we are unable to use something like

    case (2 .. 50):


    case set(‘A’,’Z’):

    Compiler must convert switch statement to optimal (binary search) sequence of if/else statements even for sets of values.

    As for return at end of each void() – yep – this can be a part of coding style for somebody 😉

  6. AT says:

    P.S> What does "12345".Substring(1,3) return ? It’s different in Java and .NET 🙁

    I’m not willing to see difference like this at syntax level.

  7. Radu Grigore says:

    I mostly agree with Eric’s argument. But I don’t see how it entails that a break-less case should be an error. A warning would work better for me.

    The code should always be warning-less, in the absence of really good reason to keep a warning. So the net effect on coding style should be just about the same: people would continue to write code that works the same way in C# and C/C++.

    On the other hand, the "break" statement in _itself_ is stupid: without fall-through it serves no purpose. So you should probably prepare for a way to eventually get rid of it. A "warning" is the best I could come up with.. 🙁

  8. I disagree with this choice.

    first break (as the name implies ) should be a loop only keyword, i dont understand how can you break a switch 🙂

    Second if a loop wraps a switch you can continue it but not break it (not orthogonal)

    and last if C++ has many problems with it, lint is there to examine it, you dont introduce useless features in a new language for the only purpose to act as a lint when you paste your C++ code in

  9. AT says:

    break is not stupid and not useless

    Take a look on this:

    int x = 1;

    bool a = true;

    switch (x)


    case 1: if (a) {


    } else {

    goto case 2;


    case 2:



  10. Radu Grigore says:

    AT, your example is analoguous to:

    void f(bool a)


    if (a) return;

    else DoSomething();


    Which doesn’t mean that it’s useful to write:

    void g()





    … which is what I was refering to. Not to mention that, as another poster pointed out, for your example a _different_ keyword would be better so that you can control the flow when switch-es and loops are nested.

    That said, I always try to avoid break/continue even within loops: the existence of break in a loop usualy means that there is no simple loop invariant so the program logic could be improved.

    I would seriously consider rewriting your example as a sequence of if-s:

    if (x==1 && a) DoA();

    if (x==1 && !a) DoB();

    if ((x==1 && !a) || x==2) DoC();

    Depending on the actual meaning of x, a, DoA, DoB, DoC it might be easier for the reader to understand this second piece of code. For example I can say instantly what code is executed when x==1 and a==true by looking at the above, while I had to think when I looked at your code. But then again, in a real situation a switch might indeed be preferable. For example if there are many particular values of x that we are interested in.

  11. Radu Grigore says:

    "while I had to think when […]"

    You should not infer from the above that thinking is causing me physical pain or anything 🙂

  12. Brett Alcorn says:

    Good work eliminating C++’s switch statement fall-through! It’s dangerous and almost never useful in practice.

    Who cares if we have to type an extra break? It’s silly to complain about that and not complain about other C++ idioms, for example the "void" keyword. Sometimes it’s just practical to use terminology we are all familiar with.

    (A pity about the goto’s, but that’s another story… 🙂

  13. Thomas Eyde says:

    Eric and others,

    It’s not about saving a few keystrokes, it’s about logic inconsistence: Fall-through is not allowed and that’s why we require the mandatory break.

  14. Joe White says:

    I’m a Delphi programmer, and Delphi’s case statements do what Chris Nahr suggested. Each case label is followed by a single statement, and if you want multiple statements, you do a block; and, there is no fallthrough. So for *me*, the "break;" is just noise, just extra typing. It doesn’t confuse me because it’s not required in my other language. Of course, Delphi programmers aren’t the majority of your target demographic.

    Personally, I’d love to see the C++ standard add a "fallthrough;" keyword, and give a warning if you don’t make your fallthroughs explicit. Then there would be no issue, and C#’s "break;" could be optional. I doubt it’ll ever happen, but it’s a nice thought.

    Oh, and please, please *don’t* add the syntax AT is asking for (the "case (2..50):"). Delphi supports that, and it’s a nightmare to maintain. You add a new value to an enum, and you have absolutely no clue how much code you just broke. It’s nice in principle, but in practice, it’s awful.

  15. Ron says:


    That in itself isn’t logical. If fall-through is not allowed and break is mandatory, then the statement is redundant and unnecessary. As Chris Nahr stated, I’d rather see case blocks only allow a single statement or explicit { } blocks.

    Of course, as AT said I’d also like the ability to create "set" cases (and also non-literals, but this would probably cause a huge uproar with the C purists). I don’t like using goto statements for continuation logic. I’m sure there are people relying on this ability. For me it’s always been an edge case I could code around.

  16. Thomas Eyde says:


    English is not my native language, so my thoughts did not come out as expected. You just made my point. Thanks.

  17. Chinh Do says:

    Explicit break statements allow for this type of fall-through (try it, it does work):

    int x=1;

    switch (x) {

    case 1:

    case 2:

    case 3:


    case 4:



  18. Thomas Eyde says:

    Get rid of the break and make us able to write it this way instead:

    int x=1;

    switch (x) {

    case 1, 2, 3:


    case 4:



  19. AT says:

    Joe: What’s wrong with 2..50 feature ?

    Was it nightmare because of weak Delphi support or it was because of some understanding complexity ?

    Even more – I would like to see something like switched if statements:

    switch(x) {

    ifcase(x<10 || x>100): goto case 2*x*(x-1);

    ifcase(x>10 && x<100):

    case 10:

    case 100:



    Compiler must check if they does not conflict.

    IDE must allow to visualise this statement.

    If you need more my crazy ideas to disagree – let me know 😉

  20. Radu Grigore says:

    AT: similar things exist in other languages for at least 10 years. so don’t worry about being to crazy. you are rather conservative: you like breaks 🙂

  21. If you’re going to require a break, why not also require a "nextcase" to allow a fall through?

  22. Joakim says:

    I never understood why switch and case needed a syntax so different from the rest of the language. If I was to define a C/C++ like language, I’d choose this syntax:





    // Do something




    // Do something else




    // It’s obvious that there is no fall trhough from this syntax,

    // and goto case(1) could still be allowed



    I see C# as one of the best attempts at breaking the evil ring of backwards compatability that crippeled the C++ syntax. I’ve grown acustom to it, but it is far from ideal, and I think keeping the syntax of the switch statement is a mistake.

Skip to main content