为什么C#允许代码块前没有声明(例如if
,else
,for
,while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
为什么C#允许代码块前没有声明(例如if
,else
,for
,while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Answers:
在您给出的上下文中,没有任何意义。将常量字符串写入控制台将在程序流程中的任何地方以相同的方式工作。1个
相反,通常使用它们来限制某些局部变量的范围。这在这里和这里进一步阐述。请查看JoãoAngelo的答案和Chris Wallis的答案,以获取简要示例。我相信同样适用于其他一些具有C样式语法的语言,尽管它们与该问题无关。
1 当然,除非您决定尝试变得有趣并创建自己的Console
类,并且使用Write()
一种可以做一些出乎意料的方法。
out
参数传递给编写的接口实现,则在混合语言项目中可以观察到这一事实用另一种语言,该实现在编写变量之前先读取该变量。
所述{ ... }
具有至少引入局部变量新范围的副作用。
我倾向于在switch
语句中使用它们以为每种情况提供不同的范围,并以这种方式允许我在使用它们的最可能位置处定义具有相同名称的局部变量,并且还表示它们仅在案例级别有效。
{}
保持这些黄金徽章来了... :)
它不是C#的功能,而是它是许多使用花括号定义scope的C语法语言的逻辑副作用。
在您的示例中,括号完全没有作用,但是在下面的代码中,它们定义了变量的范围以及可见性:
这是允许的,因为我在第一个块中超出范围,并在下一个块中再次定义:
{
{
int i = 0;
}
{
int i = 0;
}
}
这是不允许的,因为我已经超出范围,并且在外部范围中不再可见:
{
{
int i = 0;
}
i = 1;
}
等等等等。
{}
称为括号?
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;
在任何情况下,它们都不是括号,但“弯括号”似乎可以。
我认为这{}
是一个可以包含多个语句的语句。
考虑一个布尔表达式后跟一个语句的if语句。这将工作:
if (true) Console.Write("FooBar");
这也可以工作:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
如果我没记错的话,这就是一个语句块。
由于{}
可以包含其他语句,因此也可以包含other {}
。变量的范围由其父级{}
(block语句)定义。
我要说明的是,这{}
只是一条语句,因此不需要if或其他...
C语法语言的一般规则是“之间的任何事物{ }
都应视为一条语句,并且可以在一条语句可以到达的任何地方使用”:
if
。for
,while
或do
。出于所有意图和目的,这是因为语言语法包括以下内容:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
也就是说,“一个语句可以由(各种事物)或一个大括号组成,后跟一个语句列表(可能包括一个或多个语句),再由一个闭合括号组成”。IE“{ }
块可以在任何地方替换任何语句”。包括中间的代码。
{ }
实际上,不允许在单个语句可以进入的任何位置进行阻塞实际上会使语言定义更加复杂。
您问“为什么” 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
我知道可以通过为每个结构级别使用方法来更好地解决此问题。但是,再次提醒您,样本数据播种器之类的东西通常需要快速。
因此,即使上面的代码是线性执行的,代码结构也表示对象的“真实世界”结构,因此使其他开发人员更容易理解,维护和扩展。