What's with those "break" statements?
One comment from my recent post was big enough to handle separately...
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.
- 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.
- You insult all the other programmers, as they are not the target. At least not more than a minor target.
- 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
- Anonymous
November 12, 2004
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 :-) - Anonymous
November 12, 2004
The comment has been removed - Anonymous
November 12, 2004
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) - Anonymous
November 12, 2004
The comment has been removed - Anonymous
November 13, 2004
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):
or
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 ;-) - Anonymous
November 13, 2004
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. - Anonymous
November 13, 2004
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.. :( - Anonymous
November 13, 2004
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 - Anonymous
November 13, 2004
break is not stupid and not useless
Take a look on this:
int x = 1;
bool a = true;
switch (x)
{
case 1: if (a) {
break;
} else {
goto case 2;
};
case 2:
break;
} - Anonymous
November 14, 2004
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()
{
DoSomething();
return;
}
... 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. - Anonymous
November 14, 2004
"while I had to think when [...]"
You should not infer from the above that thinking is causing me physical pain or anything :) - Anonymous
November 14, 2004
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... :) - Anonymous
November 14, 2004
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. - Anonymous
November 14, 2004
The comment has been removed - Anonymous
November 14, 2004
The comment has been removed - Anonymous
November 14, 2004
Ron,
English is not my native language, so my thoughts did not come out as expected. You just made my point. Thanks. - Anonymous
November 15, 2004
The comment has been removed - Anonymous
November 15, 2004
Get rid of the break and make us able to write it this way instead:
int x=1;
switch (x) {
case 1, 2, 3:
DoSomething();
case 4:
SomethingElse();
} - Anonymous
November 15, 2004
The comment has been removed - Anonymous
November 16, 2004
The comment has been removed - Anonymous
November 16, 2004
If you're going to require a break, why not also require a "nextcase" to allow a fall through? - Anonymous
November 21, 2004
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:
switch(x)
{
case(1)
{
// Do something
}
case(2)
{
// Do something else
}
default
{
// 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. - Anonymous
December 18, 2004
Helpful For MBA Fans.