c#中的变量范围:未按预期工作
考虑一下这个代码c#中的变量范围:未按预期工作,c#,.net,scope,C#,.net,Scope,考虑一下这个代码 class Program { static void Main(string[] args) { string str; int x; for (x = 1; x < 10; x++) { str = "this"; } Console.WriteLine(str); Console.Read
class Program
{
static void Main(string[] args)
{
string str;
int x;
for (x = 1; x < 10; x++)
{
str = "this";
}
Console.WriteLine(str);
Console.ReadLine();
}
}
这种不同行为的原因是什么?。我希望在这两种情况下都能得到相同的结果
我做错了什么?原因是,在第一种情况下,编译器认为循环从未执行:
for (x = 1; x < 10; x++)
{
str = "this";
}
通过静态分析,编译器可以确定
if
语句将运行,并且str
将被赋值
将第二个示例更改为
class Program
{
static void Main(string[] args)
{
string str;
int x;
bool b = true; // With "const bool" it would work, though
if (b)
{
str = "this";
}
Console.WriteLine(str);
Console.ReadLine();
}
}
您将具有与for
循环相同的行为
即使您知道会执行for
循环,编译器也无法确定是否会执行该循环,因此它会告诉您未分配变量的原因。一个更复杂的编译器可能会发现,在这种情况下,您的变量没有问题,但是处理所有这些情况是一个非常复杂的问题
如果
x
是一个常量(这在for
循环中没有意义,因为您想增加它…),编译器将能够看到1确实小于10,并且不会警告您未使用的变量。当然循环现在将永远运行,但我这么说只是为了强调编译器只能确定常量。编译器无法确定for
循环是否会真正迭代。它可以循环0次。编译器知道if(true)
语句是无条件执行的
理论上,适当的高级编译器可以推断第一个代码块实际上是无条件执行的,但在一般情况下解决问题是不可能的(您会遇到停止问题)。编译器被迫使用启发式来合理猜测给定语句是否可到达。如果它声明路径不可到达,您可以确定地知道它不可到达。如果它说它是可访问的,那么它可能是可访问的,或者它可能是假阳性。换句话说,编译器通常会采取:
If(true){x();}
并将其转换为x()实际上,我很想知道为什么编译器不能计算循环。循环中的X被赋值为1,并与常量10进行比较。通过执行,编译器应该知道主体总是被执行的。为什么不是这样呢?@PoweredByOrange通常情况下,x
可以在比较之前由另一个线程更改。@PoweredByOrange同意。我也想know@PoweredByOrange:由于这是一个问答网站,你可以通过发布一个问题来回答你的好奇心。在此之前,我先问你一个问题。假设我写了intx;如果(ThereIsaroformasAttheOrem()){x=123;}int y=x
您是否希望编译器尝试证明Fermat的最后一个定理,并成功地得出x
已赋值的结论?如果答案是“否”,那么您可能需要精确地说明编译器应该推断哪些谓词为真,哪些谓词为假,以及应该如何进行推断。@Vache什么是静态分析???@Cody一个简单的定义是“在不运行程序的情况下分析程序的代码”。请看这里的SO和主题。@Vache基本上你的答案是我们比IDE更聪明,我认为这是错误的。@CalvinSmith请详细说明,我不明白你为什么得出这样的结论。@Vache它有更多的内存,更快的执行时间,并且可以读取二进制文件。
if (true)
{
str = "this";
}
class Program
{
static void Main(string[] args)
{
string str;
int x;
bool b = true; // With "const bool" it would work, though
if (b)
{
str = "this";
}
Console.WriteLine(str);
Console.ReadLine();
}
}