为什么必须在if语句的范围之外声明变量才能存在?
例如,以下代码无法编译:
DateTime? myDate;
if (myDate != null)
{
DateTime runDate = DateTime.Now;
}
else
{
DateTime runDate = DateTime.Now.AddDays(1);
}
string foo = runDate.toString();
我理解问题是我需要在if语句之前声明runDate
,但为什么呢?如果编译器确实允许这段代码工作,那么它真的与之前声明它有什么不同吗?或者更好的措辞,为什么从事语言/框架工作的开发人员决定这样做呢?
答案 0 :(得分:14)
好吧,考虑一下,从你的例子中得出:
DateTime? myDate;
if (myDate != null)
{
String runDate = DateTime.Now.ToString();
}
else
{
DateTime runDate = DateTime.Now.AddDays(1);
}
string foo = runDate.ToString();
根据您的提案,runDate
(分配foo
时)的类型在编译时未知,可以是string
或DateTime
。静态类型语言不允许这样做。
答案 1 :(得分:2)
变量在声明范围之外不存在。
在您的情况下,变量runDate是在if语句中创建的,因此不能在外部使用。
这是允许的
DateTime? myDate;
DateTime runDate;
if (myDate != null)
{
runDate = DateTime.Now;
}
else
{
runDate = DateTime.Now.AddDays(1);
}
string foo = runDate.toString();
答案 2 :(得分:1)
正如其他人所说 - 它是C#中本地定义的一部分:
答案 3 :(得分:0)
即使在DateTime runDate
的两边声明了if
,编译器也不知道除非进行深入分析以确保编译器不在那里。此外,在if
范围内声明超出范围,因为您在if
范围内声明,如果要在方法中使用某些内容,则需要在方法的范围,并在if
。
DateTime? myDate ;
DateTime runDate ;
if (myDate != null)
{
runDate = DateTime.Now;
}
else
{
runDate = DateTime.Now.AddDays(1);
}
string foo = runDate.toString();
答案 4 :(得分:0)
因为C#中的变量仅在其块中有效。尝试在if语句中创建runDate变量没有任何问题。失败的是,试图在它的块之外使用runDate变量。
声明必须位于其使用的最外面的块上。你当然可以在if语句中移动runDate.ToString(),如果你愿意的话,它会编译。
答案 5 :(得分:0)
由于块范围。编译器运行起来要容易得多,而且更合乎逻辑。每个块(一组开括号和闭括号)都有它的局部变量,它们只在其中的范围内,以及任何子块。这是有道理的,可以阻止人们疯狂。
答案 6 :(得分:0)
想象一下,你有以下几点:
if (something)
{
string foo = "Abc";
}
else if (somethingelse)
{
DateTime foo = DateTime.Now;
}
else
{
//Do nothing
}
Some.Method(foo); //What type is foo, string or DateTime? Does it even exist?
正如您所看到的,如果您允许在if / else块范围内声明的变量在这些块之外使用,则这些声明可能会相互冲突(甚至在某些“if”分支中丢失) “)。因此,该语言的设计者决定不允许这样做。 (另外,一般来说,块中声明的C#中的变量只能在该块中使用。仅为if语句更改此内容会很奇怪且不一致。)你仍然可以在块内声明变量,你就是不能使用这些外面的变量。
答案 7 :(得分:0)
if (condition)
{
T x;
…
}
else
{
T x;
…
}
x = …;
您的想法可能是x = …;
始终有效,因为无论x
语句采用什么路径,都保证声明if
。
这可能是对的,但这种情况实际上是一个非常特殊的情况。它只需要很少的东西,事情开始分崩离析:
else
条款 x
xor if
条款中遗漏else
声明 在这两种情况下,x
将不再保证在每种情况下都被声明,因此如果x
知道condition
为真,则编译器只会将condition
的赋值识别为有效(或者,x
具有一个值,使得该子句将被执行,分别包含condition
的声明。要知道condition
的实际可能值,编译器必须执行的不仅仅是代码的静态分析;在最糟糕的情况下,它可能必须实际运行您的代码,以及通过它的所有可能路径。但是编译器应该如何运行它只是要编译的代码......?
如果condition
的值取决于随机数生成器或用户I / O,该怎么办?这意味着编译器无法确定性地找到if
语句执行时可能具有的值condition
。简而言之,为了节省时间,编译器认为不能找出x
可能具有的值,并完全放弃非静态分析是合理的。
if
和else
条款 x = …;
声明
在这种情况下,你不会对编译器抱怨{ }
的所有人感到懊恼,对吧?
如果允许变量的“条件”声明,对代码的少量更改可能会以不同的,可能意外的方式破坏您的代码。
为了让您和您自己的生活更轻松,编译器坚持您只从引用它们的x = …;
块中引用局部变量。这有两个好处:
编译器只需执行简单的静态分析即可;不需要运行代码来分析它以进行编译(即没有鸡和蛋的问题)。
您的代码(x
)只会在您删除else
的声明时中断,而不会在您执行看似无关的操作时中断,例如删除{{1}}子句。< / p>