我有一个关于为for
循环内的变量赋值的问题。据我所知,当有可能在尚未分配变量时,编译器会发出此错误消息,如Microsoft所述。
请注意,当编译器遇到可能导致使用未分配变量的构造时,即使您的特定代码没有,也会生成此错误。
我的代码如下所示:
static void Main(string[] args)
{
int i;
for (int j = 0; j <= 5; j++)
{
i = j;
}
Console.WriteLine(i.ToString());
Console.ReadLine();
}
我认为即使在这个特定情况下i
将被分配,编译器也不会检查for
语句中的实际条件,这意味着它会处理
for (int j = 0; j <= -1; j++)
一样吗?
答案 0 :(得分:13)
由于您要在for循环中为变量i
赋值,因此编译器不够智能,无法确定是否会为其分配任何值,因此会出错。
一个简单的解决方案是为您的变量分配一些默认值。
int i = 0;
虽然从循环变量值看来控件将进入for
循环,但编译器无法确定。
错误的原因是由于语言规范,
在函数成员的可执行代码中的给定位置,a 如果编译器可以证明,变量被认为是明确分配的, 通过静态流分析,该变量已自动初始化或已成为至少一项任务的目标。
评估条件不是静态流程,它将在运行时确定。因此,编译器无法确定是否为i
分配任何值。
答案 1 :(得分:4)
您当前的案例似乎微不足道,但如果您的循环如下所示:
int i;
for (int j = 0; j <= GetUpperLimit(); j++)
{
i = j;
}
GetUpperLimit
可以返回5,就像它可以返回-3而i
永远不会被分配。它可能完全取决于运行时期间应用程序的状态,显然,编译器无法预先知道。一个简单的int i = 0
将解决问题。
如果条件为false const
或文字,则for循环将被优化掉。使用LINQPad进行演示:
int i;
for (int j = 0; j <= -1; j++)
{
i = j;
}
产生的IL:
IL_0001: ldc.i4.0
IL_0002: stloc.1 // j
IL_0003: br.s IL_000D
IL_0005: nop
IL_0006: ldloc.1 // j
IL_0007: stloc.0 // i
IL_0008: nop
IL_0009: ldloc.1 // j
IL_000A: ldc.i4.1
IL_000B: add
IL_000C: stloc.1 // j
IL_000D: ldloc.1 // j
IL_000E: ldc.i4.m1
IL_000F: cgt
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: stloc.2 // CS$4$0000
IL_0015: ldloc.2 // CS$4$0000
IL_0016: brtrue.s IL_0005
现在使用假文字而不是表达式:
int i;
for (int j = 0; false; j++)
{
i = j;
}
产生的IL:
IL_0001: ldc.i4.0
IL_0002: stloc.1 // j
IL_0003: br.s IL_0005
IL_0005: ldc.i4.0
IL_0006: stloc.2 // CS$4$0000
同样,if(false) { ... }
已经过优化,但不是bool b = false; if(b) { ... }
。这完全是静态分析的结果。