C# 未签名变量for循环的使用
我有一个关于为C# 未签名变量for循环的使用,c#,C#,我有一个关于为for循环中的变量赋值的问题。据我所知,如Microsoft所述,当变量尚未赋值时可能被读取时,编译器会给出此错误消息 请注意,此错误是在编译器遇到可能导致使用未赋值变量的构造时生成的,即使您的特定代码没有 我的代码如下所示: static void Main(string[] args) { int i; for (int j = 0; j <= 5; j++) { i = j; } Console.WriteLi
for
循环中的变量赋值的问题。据我所知,如Microsoft所述,当变量尚未赋值时可能被读取时,编译器会给出此错误消息
请注意,此错误是在编译器遇到可能导致使用未赋值变量的构造时生成的,即使您的特定代码没有
我的代码如下所示:
static void Main(string[] args)
{
int i;
for (int j = 0; j <= 5; j++)
{
i = j;
}
Console.WriteLine(i.ToString());
Console.ReadLine();
}
int i;
for (int j = 0; j <= GetUpperLimit(); j++)
{
i = j;
}
同样的?因为您在for循环中为变量
i
赋值,所以编译器不够聪明,无法看到是否会给它赋值,因此会出现错误
一个简单的解决方案是为变量指定一些默认值
int i = 0;
尽管从循环变量值来看,控件似乎将为循环输入,但编译器无法确定这一点
错误的原因是因为语言规范
在函数成员的可执行代码中的给定位置
如果编译器能够证明,
通过静态流分析,表明变量已自动初始化或已成为至少一个赋值的目标
评估条件不是静态流,它将在运行时确定。因此,编译器无法确定是否将i
赋值 您当前的案例似乎微不足道,但如果您的循环如下所示:
static void Main(string[] args)
{
int i;
for (int j = 0; j <= 5; j++)
{
i = j;
}
Console.WriteLine(i.ToString());
Console.ReadLine();
}
int i;
for (int j = 0; j <= GetUpperLimit(); 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
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
现在使用一个错误的文本而不是表达式:
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_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
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;如果(b){…}
。这是静态分析的结果。只是作为一个旁白,这是因为编译器在评估变量是否初始化时不考虑嵌套的范围,所以这是一个更一般的问题。@马格斯:我认为我不能把一个评论标记为一个被接受的答案,但是如果我可以的话,我会。我想知道它的总体外观。@Magus,你所说的嵌套作用域是什么意思,我想这是因为条件。如果您有像{{{i=10;}}}
这样的变量赋值,而不是for
循环,则不会出现任何错误。这个错误是因为编译器不能计算条件,很明显我错了。但是,它确实扩展到了某些上下文,例如try
和if
,但不是使用块的。@Kapol,原因不是嵌套的作用域,而是C#specs中指定的静态流分析。在您的示例中,编译器事先不知道这一点,这是对的,但在我的示例中,它会知道。因此出现了轻微的混乱。