C# if语句后面的变量声明

C# if语句后面的变量声明,c#,if-statement,C#,If Statement,在另一个论坛上出现了一个问题,我知道如何解决它,但它揭示了编译器特有的一个特性。此人收到错误“Embedded语句不能是声明或带标签的语句”,因为他们在没有括号的if语句后面声明了变量。这不是他们的意图,但是他们注释掉了紧跟在if语句之后的代码行,这使得变量声明成为要执行的事实代码行。无论如何,这就是背景,这让我想到了这一点 以下代码是非法的 if (true) int i = 7; 然而,如果你把它放在括号里,它是合法的 if (true) { int i = 7; } 这

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

以下代码是非法的

if (true)
    int i = 7;
然而,如果你把它放在括号里,它是合法的

if (true)
{
    int i = 7;
}

这两段代码都不是有用的。然而,第二个是好的。对这种行为的具体解释是什么

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

下面是Eric Lippert关于C#编译器关于名称解析的部分内容:

…C#不是一个“猜测用户的想法” 意思是“语言…编译器” 如果是最好的,设计会大声抱怨 匹配是不起作用的


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

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

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

示例代码

void F(bool b) {
    if (b)
        int i = 44;
}
本章区分了三种类型的陈述(更多详细信息,请参见第8章)。通常,您可以使用以下语句:

  • 标记语句-我猜这是针对老式的
    goto
    语句
  • 声明语句-这将是一个变量声明
  • embedded语句—它几乎包括所有剩余的语句
if
语句中,主体必须嵌入语句,这解释了为什么第一个版本的代码不起作用。以下是规范中的
if
(第8.7.1节)的语法:

if(布尔表达式)嵌入语句
if(布尔表达式)嵌入语句else嵌入语句


变量声明是声明语句,因此它不能出现在主体中。如果将声明括在括号中,您将得到一个语句块,它是一个嵌入式语句(因此它可以出现在该位置)。

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

我同意,以这种方式声明变量毫无意义。然而,第二个例子中完全无用的变量声明是可以的。两者都没有价值。这仅仅是一个括号的问题,而不是别的问题吗?(顺便说一句,我可以接受。)是的。当您包含括号时,编译器完全清楚您的意图,因此它将允许这样做。C#编译器不允许使用括号,因为不清楚您的实际意图是否是声明一个无用的变量。但是第二个变量很可能很有价值——例如,如果从一个有副作用的方法检索值。感谢Eric在这方面的帖子链接。现在我知道了最近一个博客系列的起源。谢谢你的投入,非常有益。