为什么C#允许{}代码块没有前面的语句?


86

为什么C#允许代码块前没有声明(例如ifelseforwhile)?

void Main()
{
    {   // any sense in this?
        Console.Write("foo");
    }
}

70
有什么理由不应该这样做吗?
Jamiec

30
但是,正如答案所表明的那样,它具有的意义不仅仅是“不受伤,所以就让它”。这是提出此类问题的重点。
Seldon

8
+1问题听起来很无辜,但答案确实教会了我一些宝贵的知识
Nicolas78

7
@Akash:不问为什么,我们永远不会变得更好。
理查德

7
@Akash:这似乎是高尚的精英主义态度。人们总是有疑问,如果没有理由问为什么,那么拥有SO是没有意义的。这个站点并不是为了让人们解决我们的紧迫问题(尽管确实发生了),而是提供一个问题和答案的资料库,这将帮助我们所有人成为更好的程序员。所以是问为什么!:-)
理查德

Answers:


90

在您给出的上下文中,没有任何意义。将常量字符串写入控制台将在程序流程中的任何地方以相同的方式工作。1个

相反,通常使用它们来限制某些局部变量的范围。这在这里这里进一步阐述。请查看JoãoAngelo的答案Chris Wallis的答案,以获取简要示例。我相信同样适用于其他一些具有C样式语法的语言,尽管它们与该问题无关。


1 当然,除非您决定尝试变得有趣并创建自己的Console类,并且使用Write()一种可以做一些出乎意料的方法。


24
回复:其他语言:通常但并非总是如此。JavaScript是一个明显的例外。在特定块中声明局部变量不会将该变量限制在该块范围内。
埃里克·利珀特

@EricLippert:在C#中,是否在块中声明变量会导致变量在运行时的范围内变化?据我所知,变量的生命周期通常不受作用域块的限制,如果在循环中对变量进行的第一件事是将其作为out参数传递给编写的接口实现,则在混合语言项目中可以观察到这一事实用另一种语言,该实现在编写变量之前先读取该变量。
超级猫

在C ++中,由于使用了RAII而不是GC,因此它更加有用。
Deduplicator

在C ++中,它的行为很像try / catch块,因此在离开该范围时,在该范围内声明的变量和类会弹出堆栈。这有助于防止名称冲突并减少功能的内存占用。它还从代码编辑器的自动完成中删除那些变量。我经常发现try / catch块更有用。
Kit10

144

所述{ ... }具有至少引入局部变量新范围的副作用。

我倾向于在switch语句中使用它们以为每种情况提供不同的范围,并以这种方式允许我在使用它们的最可能位置处定义具有相同名称的局部变量,并且还表示它们仅在案例级别有效。



6
如果您需要使用示波器,则它们太大了!提取方法。
周杰伦·巴祖兹

20
@Jay Bazuzi,只是因为我想在多个情况下使用具有相同名称的局部变量,并不意味着它们必须很大。你只是跳到巨大的结论... :)
若昂·安杰洛

恭喜,您获得了Great Answer徽章!:)
BoltClock

1
@BoltClock,谢谢,我只是需要一些更多的问题,您来{}保持这些黄金徽章来了... :)
若昂·安杰洛

56

它不是C#的功能,而是它是许多使用花括号定义scope的C语法语言的逻辑副作用。

在您的示例中,括号完全没有作用,但是在下面的代码中,它们定义了变量的范围以及可见性:

是允许的,因为我在第一个块中超出范围,并在下一个块中再次定义:

{
    {
        int i = 0;
    }

    {
        int i = 0;
    }
}

是不允许的,因为我已经超出范围,并且在外部范围中不再可见:

{
    {
        int i = 0;
    }

    i = 1;
}

等等等等。


1
我已经读过关于各种英语风格的括号命名法的差异,但是哪种风格{}称为括号?
BoltClock

好问题!我想十年前我的导师将其植入了我的大脑。我可能应该称它们为“花括号”或“花括号”。每个人都有自己的... en.wikipedia.org/wiki/…–
克里斯·沃利斯

10
在我的vocab中,'('=括号,'{'=大括号,'['=方括号
pb。

等等,我称它们为大括号,而Wikipedia包含该命名。牛津英语词典将方括号的用法定义为: One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context; 在任何情况下,它们都不是括号,但“弯括号”似乎可以。
dumbledad

IME,“花括号”和“方括号”。
cp.engr 16/09/14

18

我认为这{}是一个可以包含多个语句的语句。

考虑一个布尔表达式后跟一个语句的if语句。这将工作:

if (true) Console.Write("FooBar");

这也可以工作:

if (true)
{
  Console.Write("Foo");
  Console.Write("Bar");
}

如果我没记错的话,这就是一个语句块。

由于{}可以包含其他语句,因此也可以包含other {}。变量的范围由其父级{}(block语句)定义。

我要说明的是,这{}只是一条语句,因此不需要if或其他...


+1这正是C样式语言中的花括号-所谓的“复合语句”。
Michael Ekstrand

12

C语法语言的一般规则是“之间的任何事物{ }都应视为一条语句,并且可以在一条语句可以到达的任何地方使用”:

  • 过了一会儿if
  • 之后forwhiledo
  • 代码中的任何地方

出于所有意图和目的,这是因为语言语法包括以下内容:

     <statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>

也就是说,“一个语句可以由(各种事物)或一个大括号组成,后跟一个语句列表(可能包括一个或多个语句),再由一个闭合括号组成”。IE“{ }块可以在任何地方替换任何语句”。包括中间的代码。

{ }实际上,不允许在单个语句可以进入的任何位置进行阻塞实际上会使语言定义更加复杂


有人刚刚提出了这个答案(9年后),这实际上不是这个问题的具体答案,而是更多的一般性讨论。语言和库已经取代了它。
Massimo

1

因为C ++(和Java)允许代码块不带前面的语句。

C ++允许它们,因为C允许。

您可以说这全都归结为事实,即美国程序语言(基于C)的设计胜于欧洲程序语言(基于Modula-2)的设计。

(控制语句作用于单个语句,语句可以成组创建新的语句)


您是说Module2还是Modula2?
理查德·伊夫

确实,这是正确的答案。此外,我只想回答“因为每种计算机语言都可以。”
Fattie


0

1因为...它维护语句的作用域..或函数,这对于处理大型代码确实很有用。

{
    {
        // Here this 'i' is we can use for this scope only and out side of this scope we can't get this 'i' variable.

        int i = 0;
    }

    {
        int i = 0;
    }
}

在此处输入图片说明


0

您问“为什么” C#允许没有前面的语句的代码块。问题“为什么”也可以解释为“这种结构可能带来什么好处?”

就个人而言,我在C#中使用无语句代码块,对于其他开发人员而言,其可读性得到了极大的提高,同时请记住,代码块限制了局部变量的范围。例如,考虑以下代码片段,由于有了附加的代码块,它更易于阅读:

OrgUnit world = new OrgUnit() { Name = "World" };
{
    OrgUnit europe = new OrgUnit() { Name = "Europe" };
    world.SubUnits.Add(europe);
    {
        OrgUnit germany = new OrgUnit() { Name = "Germany" };
        europe.SubUnits.Add(germany);

        //...etc.
    }
}
//...commit structure to DB here

我知道可以通过为每个结构级别使用方法来更好地解决此问题。但是,再次提醒您,样本数据播种器之类的东西通常需要快速。

因此,即使上面的代码是线性执行的,代码结构也表示对象的“真实世界”结构,因此使其他开发人员更容易理解,维护和扩展。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.