出于所有意图和目的(除了捕获的变量之外),这是:
for (int i = 0; i < 10; i++)
....
可以重写为:
int i = 0;
while (i < 10)
{
....
i++;
}
正如您所看到的,迭代仅在条件为 false 时停止,而要使条件为 false,i 必须等于或大于 10。
事实上,如果我尝试这个程序LINQPad http://linqpad.net:
void Main() { }
public static void Test1()
{
for (int i = 0; i < 10; i++)
Console.WriteLine(i);
}
public static void Test2()
{
int i = 0;
while (i < 10)
{
Console.WriteLine(i);
i++;
}
}
然后检查生成的 IL,让我将这两个方法并排放置:
Test1: Test2:
IL_0000: ldc.i4.0 IL_0000: ldc.i4.0
IL_0001: stloc.0 // i IL_0001: stloc.0 // i
IL_0002: br.s IL_000E IL_0002: br.s IL_000E
IL_0004: ldloc.0 // i IL_0004: ldloc.0 // i
IL_0005: call System.Console.WriteLine IL_0005: call System.Console.WriteLine
IL_000A: ldloc.0 // i IL_000A: ldloc.0 // i
IL_000B: ldc.i4.1 IL_000B: ldc.i4.1
IL_000C: add IL_000C: add
IL_000D: stloc.0 // i IL_000D: stloc.0 // i
IL_000E: ldloc.0 // i IL_000E: ldloc.0 // i
IL_000F: ldc.i4.s 0A IL_000F: ldc.i4.s 0A
IL_0011: blt.s IL_0004 IL_0011: blt.s IL_0004
IL_0013: ret IL_0013: ret
然后您可以看到它生成了完全相同的代码。
现在,编译器将确保您无法编写代码after尝试访问变量的 for 循环,但是如果您捕获该变量,如代码所示,那么您将像循环结束时一样访问该变量,并且只有当条件为 false 时,循环才会自行结束。
因此,你的假设是i
如果为 false,则等于字符串中最后一个字符的索引,它将等于刚刚过去的索引,因此当您尝试执行委托时,您将得到索引超出范围的异常。
这是一个简单的.NET 小提琴 https://dotnetfiddle.net/hqKN6k这表明该程序:
using System;
public class Program
{
public static void Main()
{
Action a = null;
for (int index = 0; index < 10; index++)
a = () => Console.WriteLine(index);
a();
}
}
输出 10。