这是允许的:
// scope_1
int i = 100;
if (i > 50)
{
// scope_2
int a = 200;
}
这会出错:
// scope_1
if (100 > 50)
int a = 200;
第二个代码示例的原因是否由于范围而导致错误?因此编译器不允许在条件语句求值为true时声明特定作用域内的变量 a ,因为如果它确实允许,那么编译器就无法确定是否允许在scope_1中声明另一个名为 a 的变量?
答案 0 :(得分:13)
if (100 > 50)
int a = 200;
你为什么要这样做?在声明为变量的单语句范围内声明变量似乎没有意义,因为您实际上没有时间使用声明的变量。
如果允许您在a
语句之外引用if
,则上述操作将导致条件变量声明。但是,声明不能是有条件的。编译器在遇到可以声明或未声明的标识符时可以合理地做些什么?无论哪种情况都只能在运行时计算出来,而不是在编译时;但编译器需要知道(因为未声明的标识符是语法错误),因此它会抱怨这个结构。
答案 1 :(得分:8)
您在if
语句中没有使用括号,因此此后只允许使用一个语句。如果变量无法被引用,那么对变量进行尺寸标注有什么意义呢?
此外,您的第二个if
语句使用文字常量,显然永远不会成立。再说一次,将任何内容放入其中是什么意思?
也许我误解了你的问题。
答案 2 :(得分:5)
让我稍微改一下你的问题。
规范的哪个部分定义了这种行为?
第8.7.1节规定“if”的陈述是“嵌入式陈述”。
第8节的开头指出嵌入语句可以是块或空,表达式,选择,迭代,跳转,尝试,检查,取消选中,锁定,使用或屈服语句,但不是带标签的语句或声明言。
为什么不允许声明声明?
原始语言笔记没有涉及这个特定点,但我们可以做一些有根据的猜测。你的猜想很好;这样做会使得很难推断所声明的本地范围。如果我们允许它,那么我们必须决定“if”是否隐式地创建一个局部变量声明范围,即使没有块:
if (x) int y = M();
else string y = N();
这是重新声明的本地变量错误吗?或条件的每个分支是否产生自己的局部变量声明空间?
这个怎么样?
if(x) int y = M();
else y = N();
Q(y);
y是否在范围之外?如果是这样,它是否在到达Q(y)时被明确分配?
我对这里正确的事情没有强烈的直觉。无论我们选择哪一个,似乎有一半的人会认为我们选错了。如果你想引入一个新的局部变量声明空间,那么更好的做法是使整个认为非法并需要括号。
现在有些问题没有问:
开关块怎么样?是否适用相同的规则?
没有。阅读本文:
http://ericlippert.com/2009/08/13/four-switch-oddities/
如果我合法地声明一个局部变量但只分配给它,会发生什么情况,就像我在带有条件的结果中的块的例子一样?
有时你会收到警告。有时候你没有。
编译器如何决定是否发出警告?
阅读本文:
答案 3 :(得分:3)
看看你的第二个案例:
if (100 > 50)
int a = 200;
您声明的变量“a”只能在该单个语句中使用。但是,它是一个l值,因此定义变量的整个目的是稍后使用它。
你做不到(出于显而易见的原因):
if (100 > 50)
int a = 200;
Console.WriteLine(a); // This makes no sense... What happens if 100 < 50????
编译器足够聪明,在这种情况下会出错,因为如果允许的话,你真的无法使用该变量。
答案 4 :(得分:2)
因为您无法访问{}的访问权限。如果编译器允许你这样做,变量的范围
一
仅限于大括号。
// scope_1
int i = 100;
if (i > 50)
{
// scope_2
int a = 200;
}
// if you will try
int anotherA = a; // a does not exist in the current context
答案 5 :(得分:2)
看看
if不是强制性的 声明如果我们想要{} 将其范围限制为只有一行。 但是,我们不能有变量 声明作为以下唯一的一行 它。这是因为如果条件 结果为假,变量会 永远不会被创造。
另外看看
Statements (C# Programming Guide)
不是的嵌入式语句 括在{}括号内不能是一个 声明或声明 言。
答案 6 :(得分:1)
创建第二个范围只包含一条指令,因此声明一个变量(已经是一条指令)是没用的,因为它只能在该范围内使用。
编译器永远不会错!
答案 7 :(得分:1)
这与编辑器智能与“范围”无关,a
是否在if
之外可见。
C89标准不允许任何一种构造。在C99中,您可以在块的开头(复合语句)声明一个变量,而不是其他地方。
此代码没有块:
if ( i )
int a = 100;
它也没有隐含的阻止 - 这可能就是你在想的。 “if”后面可以跟一个语句或复合语句。复合语句是允许您拥有声明列表的地方。上面的内容只是一个声明。
您可以通过添加{}来将其转换为复合语句。
if (
表达 )
声明
其中语句可以是单个语句,也可以是复合语句。
复合语句:
{
声明列表 声明列表}
(另见K&amp; R 2ed A9.3“化合物声明”)
如上所述,这是一个C#问题。 C#标准在第15.2节中对此进行了讨论,但并不简洁。 :)基本上,声明需要一个块。块需要括号。故事结束。
答案 8 :(得分:1)
您得到的错误是:
error CS1023: Embedded statement cannot be a declaration or labeled statement
这意味着 if-statement 的语法需要条件表达式后面的语句或语句块
if-stmt -> 'if' '(' expr ')' stmt ['else' stmt]
stmt -> if-stmt
-> do-stmt
-> ...etc...
-> '{' [declaration...] [stmt...] '}'
声明不是声明,因此这是一个简单的语法错误。