tags:

views:

154

answers:

3

An issue came up on another forum and I knew how to fix it, but it revealed a feature of the compiler peculiar to me. The person was getting the error "Embedded statement cannot be a declaration or labeled statement" because they had a declaration of a variable following an if statement with no brackets. That was not their intent, but they had commented out the line of code immediately following the if statement, which made the variable declaration the de facto line of code to execute. Anyway, that's the background, which brings me to this.

The following code is illegal

if (true)
    int i = 7;

However, if you wrap that in brackets, it's all legal.

if (true)
{
    int i = 7;
}

Neither piece of code is useful. Yet the second one is OK. What specifically is the explanation for this behavior? I have a hypothesis, but I'd rather ask the brilliant people on stackoverflow.

+8  A: 

When you don't include the brackets, it executes the next line as if it were surrounded by brackets. Since it doesn't make much sense to declare a variable in that line (you wouldn't be able to use it ever), the C# compiler will not allow this to prevent you from accidentally doing it without knowing (which might introduce subtle bugs).

Here's part of Eric Lippert has to say about the C# compiler on this SO answer about name resolution:

...C# is not a "guess what the user meant" language...the compiler by design complains loudly if the best match is something that doesn't work

Zach Johnson
I agree, it doesn't make sense at all to declare a variable in such a manner. Yet the completely useless variable declartion in the second example is fine. Neither is of value. Is it simply a matter of bracketing, nothing else? (I can live with that, by the way.)
Anthony Pegram
Yes. Your intentions are absolutely clear to the compiler when you include the brackets, so it will allow that. The C# compiler will not allow it without brackets, since it is not clear that your actual intention is to declare a useless variable.
Zach Johnson
But the second could very well be of value - if, for example, the value is being retrieved from a method that has side effects.
Andrew Medico
Thanks for the link to Eric's post on that. Now I know where a recent blog series originated.
Anthony Pegram
+3  A: 

All compilers will allow you to compile code that is useless or of exceedingly low use. There are simply too many ways that a developer can use the language to create constructs with no use. Having the compiler catch all of them is simply too much effort and typically not worth it.

The second case is called out directly in the C# language specification at the start of section 8.0

The example results in a compile-time error because an if statement requires an embedded-statement rather than a statement for its if branch. If this code were permitted, then the variable i would be declared, but it could never be used. Note, however, that by placing i’s declaration in a block, the example is valid.

Example Code

void F(bool b) {
    if (b)
        int i = 44;
}
JaredPar
Thanks for the input, very beneficial.
Anthony Pegram
+11  A: 

The C# language specification distinguishes between three types of statements (see chapter 8 for more details). In general you can have these statements:

  • labeled-statement - my guess that this is for the old-fashioned goto statement
  • declaration-statement - which would be a variable declaration
  • embedded-statement - which includes pretty much all the remaining statements

In the if statement the body has to be embedded-statement, which explains why the first version of the code doesn't work. Here is the syntax of if from the specification (section 8.7.1):

if ( boolean-expression ) embedded-statement
if ( boolean-expression ) embedded-statement else embedded-statement

A variable declaration is declaration-statement, so it cannot appear in the body. If you enclose the declaration in brackets, you'll get a statement block, which is an embedded-statement (and so it can appear in that position).

Tomas Petricek
First one to quote the spec wins! Thanks to everyone.
Anthony Pegram