2010-03-22 148 views
56

在另一个论坛上出现了一个问题,我知道如何解决它,但它揭示了编译器特有的一个特性。该人收到错误“嵌入式语句不能是声明或标记语句”,因为他们在if语句后没有括号的情况下声明了变量。这不是他们的意图,但是他们已经将if语句之后的代码行注释掉了,这使得变量声明成为事实上的代码行来执行。无论如何,这是背景,这使我想到了这一点。if语句后面的变量声明

下面的代码是非法的

if (true) 
    int i = 7; 

但是,如果包裹在括号中,它的所有法律。

if (true) 
{ 
    int i = 7; 
} 

这两段代码都没有用。然而第二个是确定的。这个行为的具体解释是什么?

回答

76

C# language specification三种类型的语句(参见第8章区分调出更多细节)。一般来说,你可以有以下语句:

  • 标记语句 - 我的猜测,这是老式goto声明
  • 声明,声明 - 这将是一个变量声明
  • 嵌入语句 - 其中几乎包含所有其余的语句

if声明机构必须是嵌入式声明,这解释了为什么代码的第一个版本不起作用。以下是规范中的if的语法(第8.7节)。1):

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

变量声明是声明陈述,因此它不能在体内出现。如果将括号内的声明括起来,您将得到一个声明块,这是一个嵌入语句(因此它可以出现在该位置)。

27

如果不包含括号,它会执行下一行,就像它被括号括起来一样。由于在该行中声明一个变量没有多大意义(您将无法使用该变量),因此C#编译器不会允许您在不知情的情况下意外执行该操作(这可能会引入细微的错误)。

这里的埃里克利珀的部分必须说关于this SO answer C#编译器有关名称解析:

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

+1

我同意加括号,它没有任何意义可言申报以这种方式变化。然而,第二个例子中完全无用的变量声明没有问题。没有价值。这仅仅是一个括号问题,没有别的? (顺便说一句,我可以和他一起生活)。 – 2010-03-22 23:58:26

+3

是的。当你包含括号时,你的意图对编译器来说是绝对清楚的,所以它会允许的。 C#编译器不会在没有括号的情况下允许它,因为不清楚您的实际意图是声明无用变量。 – 2010-03-23 00:00:37

+0

但是第二个可能非常有价值 - 例如,如果从具有副作用的方法中检索值。 – 2010-03-23 00:08:49

9

所有的编译器将允许您编译代码,无用或极低的使用。开发人员可以使用该语言创建没有用处的结构的方式太多了。让编译器抓住所有这些都是非常费力,通常不值得。

第二种情况是直接在C#语言规范在区间的开始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.

示例代码

void F(bool b) { 
    if (b) 
     int i = 44; 
} 
+0

感谢您的意见,非常有益。 – 2010-03-23 00:14:25

0

在if的其他部分添加闭合和开启大括号,就像我在下面做的那样帮助我,而不是在添加它们之前做的事情;

之前:这引起了错误:

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

后:在else分支

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