views:

528

answers:

12
+7  Q: 

C# Empty Statement

The C# language specification defines the empty-statement grammar production, which allows me to do something like this:

static void Main(string[] args)
{
    ; ; ;
}

Why would Microsoft include this grammar production in the C# language? Does it have a useful purpose?

+4  A: 

C# inherits a lot from the C family, where you can do things like

for (i = 0; i < n; v[i++] = 1);

or

while (testSomeCondition());

That is, run a loop with an empty body where the "meat" is inside the brackets.

While one can debate about their merits and dangers, these are pretty common programming idioms in the C programming world, so this backward compatibility makes it easier for C/C++/Java programmers to learn C#.

Péter Török
+5  A: 

Here are two uses:

while(DoSomething()) ;

and

void M() {
    if(someCondition) goto exit;
    // ...
    exit: ;
}

There are many others. It's a useful device anytime there is nothing to do but a statement is required.

Jason
no GOTOs please! :)
Andrey
no "no GOTOs please! :)" please! :)
Jason
I would remove that goto label and make `goto exit` a `return;`. This is awful C#.
Dykam
goto has its place, maybe not in Jason's context, but it is perfectly valid.
Yuriy Faktorovich
agree, if you want to write gotos may be you decomposed your task not that well
Andrey
Sidenote, I am not anti goto, goto is just one of those things which are to be used very, very carefully.
Dykam
http://weblogs.asp.net/stevewellens/archive/2009/06/01/why-goto-still-exists-in-c.aspx
Yuriy Faktorovich
Actually, I've used the empty statement *exactly* like this in a code generator for a state machine. Sometimes code would follow the label, but not always - the empty statement suppressed a compiler warning that liked to appear in the latter case.
280Z28
goto is fundemental. Nearly all execution flow logic compiles with goto instructions. Purposely avoiding them leads to confusing logic. Look at Microsoft's .NET souce code and you will find goto is used fairly often.
AMissico
Breaking out of deeply nested loops?
tomfanning
To all those who parrot NO GOTO - read the above comments please. Goto is fundamental, and has places it's a good option. For example a return statement in deep loop is a GOTO!
Preet Sangha
@tomfanning, exactly. Goto is a clean way to do this.
Dykam
I agree as well. I've run across some awful code that was made needlessly complex because of a dogmatic avoidance of GOTOs. Besides, successful developers who started with assembler or early FORTRAN used GOTOs through careful and thoughtful programming practices.
ebpower
A: 
if (b1)
   if (b2) else;
else
   //code

withoud this ; this will be painful. but this is not best way to write ifs also. but acceptable.

Andrey
What's a use case of this? Looks pretty useless.
Dykam
Not for every construct there is a really useful use case. Sometimes it might just be convenient when tweaking code and testing stuff.
phresnel
it is useful. if you want to write else it will be one for innermost if, like bracket. but i want to have else in outer most if.
Andrey
But if you format your code properly and have brackets around your if statements, you won't have this problem at all.
Charles Boyung
i didn't say there is a problem. i showed example of using empty statement, i didn't say that you should use it. also C# compiler will give you a warning for that.
Andrey
Isn't this the same as if (!b1) //code
recursive
+1  A: 

Good practice or not, some people use this:

while (!SomeCondition)
    ; // <-- body of the while loop is an empty statement
280Z28
+8  A: 

I personally would never use an empty statement. If I for some bizarre reason wanted to play code golf and write something like

while(Foo(x++)) ;

I'd be more inclined to use {} instead of ; as the "do nothing statement". I think that is more clear.

Pretty much it's there for historic reasons. There's nothing there that you cannot also do with {}.

UPDATE: I just thought of one possible usage case. In a debug build it allows you to put a breakpoint somewhere that you are guaranteed that you can break at which is not going to have any side effect when you step. If the code surrounding the breakpoint is particularly complicated it might be useful.

UPDATE UPDATE: I am WRONG WRONG WRONG. That doesn't work. It just moves the breakpoint to the next statement. How irksome.

Eric Lippert
Though, golfing is usually by character, and `{}` is 1 more character than `;`... :p
Tanzelax
BTW, you can't set a breakpoint at an empty statement. It skips over the breakpoint and brings you to the next non-empty statement. Just tried it...
James Jones
If you have a second Eric could you add a comment to my answer on this question whether I'm on base or not.
Chris Marisic
@James: Hmm. You're right. How vexing!
Eric Lippert
A: 

Eric Lippert's a good person to ask.

Mostly, I suppose it's because it wouldn't cause any harm and it simplified their handling of the grammar. Also, why restrict people when you don't have to?

Jim Leonardo
+10  A: 
while (GetWhitespace(textStream))
    ;
Jeffrey L Whitledge
+1  A: 

Why would Microsoft include this grammar production in the C# language?

the main answer to this question is: C# is C-like language and to make life of different developers easier MS decided to make most basic syntax elements compatible with other c-like languages. and it is good.

Andrey
A: 

For what it's worth, a good rule of thumb is that you should have stepped through in the debugger every line of code you write, at least once for each possible execution path

ref: Possible mistaken empty statement

Asad Butt
+2  A: 

It allows have blocks of code IFDEF'd out, and the surrounding code still build. eg

if(true){
#if(DEBUG)
System.Console.WriteLine("Debug comment");
#endif
}

which could be written as an empty block, if you dislike brackets:

if(true)
#if(DEBUG)
   System.Console.WriteLine("Debug comment")
#endif
;
Simeon Pilgrim
Your example doesn't actually show an empty statement.
tomfanning
Yes it does, {} looks pretty empty to me, about as empty as {;}, the {} acts as a block marker, so does the ; in the second case.
Simeon Pilgrim
While {} is "a statement that doesn't do anything", it's not the C# "empty statement" as defined here: http://msdn.microsoft.com/en-us/library/aa664739%28VS.71%29.aspx
tomfanning
Ok, good point, I see he's referring to the grammar rule, thus your correct. Therefore grammar the rule you point to is the perfect answer.
Simeon Pilgrim
+2  A: 

This is an assumption but I would assume it goes to the base grammar for the compiler. Relating it to set theory the "empty set" is inside every single set. That the ; really is to define a set of lexical operations which always must define the ; which also would accept the base case which is empty statement.

Chris Marisic
First off, the empty set is a *subset* of every set, but not a *member* of every set; "inside" is ambiguous as to which you mean. Second, I'm not following your point about how that applies to grammar design.
Eric Lippert
It's been a while since my compiler theory has ever been needed but in I believe the lexical parser that evaluates whether expressions are valid that are like A | [B]A | [B]C[B]A where A in this case is the ;
Chris Marisic
+1  A: 

So some genius could write for(;;) instead of while(true). Like for an interview test.

ebpower
Think you mean `for(;;)`. for(;;;;) won't compile. `For` does ignore standard rules really.
Dykam
Oops-good catch. Here's a treatment on their assembly level equivalence: http://stackoverflow.com/questions/2288856/when-implementing-an-infinite-loop-is-there-a-difference-in-using-while1-vs-fo
ebpower