【问题标题】:Variable declarations following if statementsif 语句后的变量声明
【发布时间】:2010-03-22 23:54:55
【问题描述】:

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

以下代码不合法​​

if (true)
    int i = 7;

但是,如果你把它放在括号里,那就是合法的。

if (true)
{
    int i = 7;
}

这两段代码都没有用。不过第二个还行。这种行为的具体解释是什么?

【问题讨论】:

    标签: c# if-statement


    【解决方案1】:

    C# language specification 区分三种类型的语句(有关详细信息,请参阅第 8 章)。一般来说,你可以有这些语句:

    • labeled-statement - 我猜这是针对老式的 goto 声明
    • declaration-statement - 这将是一个变量声明
    • embedded-statement - 包括几乎所有剩余的语句

    if 语句中,主体必须是embedded-statement,这解释了为什么第一版代码不起作用。以下是规范(第 8.7.1 节)中if 的语法:

    if ( boolean-expression ) 嵌入式语句
    if ( boolean-expression ) embedded-statement else embedded-statement

    变量声明是declaration-statement,所以它不能出现在正文中。如果将声明括在方括号中,您将得到一个语句块,它是一个 embedded-statement(因此它可以出现在那个位置)。

    【讨论】:

      【解决方案2】:

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

      这里是 Eric Lippert 的一部分,关于名称解析的 this SO answer 上的 C# 编译器:

      ...C# 不是“猜用户 意思是“语言...编译器由 如果最好,设计会大声抱怨 匹配是行不通的

      【讨论】:

      • 我同意,以这种方式声明变量完全没有意义。然而,第二个示例中完全无用的变量声明很好。两者都没有价值。仅仅是括号的问题,没有别的吗? (顺便说一句,我可以忍受。)
      • 是的。当您包含括号时,您的意图对编译器来说是绝对清楚的,因此它将允许这样做。 C# 编译器不允许它没有括号,因为不清楚你的实际意图是声明一个无用的变量。
      • 但是第二个很可能很有价值 - 例如,如果从具有副作用的方法中检索该值。
      • 感谢 Eric 的帖子链接。现在我知道最近的博客系列起源于哪里了。
      【解决方案3】:

      所有编译器都允许您编译无用或使用率极低的代码。开发人员可以通过多种方式使用该语言来创建无用的构造。让编译器捕获所有这些只是太多的努力,而且通常不值得。

      第二种情况在C#语言规范第8.0节开头直接调用

      该示例导致编译时错误,因为 if 语句需要嵌入语句而不是其 if 分支的语句。如果允许此代码,则变量 i 将被声明,但它永远无法使用。但是请注意,通过将 i 的声明放在块中,该示例是有效的。

      示例代码

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

      【讨论】:

      • 感谢您的意见,非常有益。
      【解决方案4】:

      在 if 的 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
              // 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);
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-29
        • 2014-04-12
        • 2014-08-26
        • 2016-01-13
        • 1970-01-01
        • 2021-03-04
        相关资源
        最近更新 更多