使用未分配的变量 - for循环

时间:2014-01-29 19:11:09

标签: c#

我有一个关于为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++)

一样吗?

2 个答案:

答案 0 :(得分:13)

由于您要在for循环中为变量i赋值,因此编译器不够智能,无法确定是否会为其分配任何值,因此会出错。

一个简单的解决方案是为您的变量分配一些默认值。

int i = 0;

虽然从循环变量值看来控件将进入for循环,但编译器无法确定。

错误的原因是由于语言规范,

5.3 Definite assignment

  

在函数成员的可执行代码中的给定位置,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) { ... }。这完全是静态分析的结果。