Variable declarations following if statements

C#If Statement

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

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).

Solution 2 - C#

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

Solution 3 - C#

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;
}

Solution 4 - C#

Adding the closing and opening braces on the else part of the if helped me like i have done below as opposed to what i was doing before adding them;

Before: this caused the error:

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {

            CATEGORY cat = new CATEGORY
            {

                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()

            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        // missing brackets - this was causing the error
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);
        
        btnSearchCat_Click(btnSearchCat, e);
    }

After: Added brackets in the else branch

protected void btnAdd_Click(object sender, EventArgs e)
    {
        if (btnAdd.Text == "ADD")
        {

            CATEGORY cat = new CATEGORY
            {

                NAME = tbxCategory.Text.Trim(),
                TOTALSALEVALUE = tbxSaleValue.Text.Trim(),
                PROFIT = tbxProfit.Text.Trim()

            };
            dm.AddCategory(cat, tbxCategory.Text.Trim());
        }
        else
        {
            var c = getCategory();
            c.NAME = tbxCategory.Text.Trim();
            c.TOTALSALEVALUE = tbxSaleValue.Text.Trim();
            c.PROFIT = tbxProfit.Text.Trim();
            dm.UpdateCategory(c);
        }
        btnSearchCat_Click(btnSearchCat, e);
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnthony PegramView Question on Stackoverflow
Solution 1 - C#Tomas PetricekView Answer on Stackoverflow
Solution 2 - C#Zach JohnsonView Answer on Stackoverflow
Solution 3 - C#JaredParView Answer on Stackoverflow
Solution 4 - C#Kristin KabajwisaView Answer on Stackoverflow