我试图理解这个问题的答案Why am I getting wrong results when calling Func<int>?我写了一些示例代码。以下代码
public static void Main(string[] args)
{
var funcs = new List<Func<string>>();
for(int v=0,i=0;v<3;v++,i++)
{
funcs.Add( new Func<string>(delegate(){return "Hello "+ i++ +" "+v;}) );
}
foreach(var f in funcs)
Console.WriteLine(f());
}
生成
Hello 3 3
Hello 4 3
Hello 5 3
在阅读Jon Skeet和Eric Lippert的解释后,我想我会得到
Hello 3 3
Hello 3 3
Hello 3 3
这里v和i都是循环变量,而i的值在那个瞬间被拾取v不是为什么这个?我不明白这种行为。
答案 0 :(得分:11)
嗯,你正确理解了Eric和Jon,但是你错过了代码的一部分:
"Hello "+ i++ +" "+v;
^^^
this part increments i for each call
基本上,发生的事情与此相似:
i
和v
的内容,然后递增i
i
和v
的内容,因为这与前一个方法调用相同i
,您将在此输出4,而不是3 另一方面,如果您通过捕获循环范围内的变量来更改代码,请执行以下操作:
for(int v=0,i=0;v<3;v++,i++)
{
int ii = i, vv = v;
funcs.Add( new Func<string>(delegate(){return "Hello "+ ii++ +" "+vv;}) );
}
然后你会得到0, 0
,1, 1
和2, 2
。你仍然在增加ii
变量,你在循环中使用捕获的值之后就这样做了,但是你再也不用那个变量了(每个匿名方法都有它自己的私有副本。)谢谢@ferosekhanj评论
答案 1 :(得分:2)
答案很简单:++i
在您的委托中执行,因此每次都会增加值。第一个值为3,因为这是循环后i的值
了解您的委托未在for
循环内执行,而是在foreach
循环中执行。
答案 2 :(得分:2)
结果是正确的(怎么可能不是?;)) 当你执行委托时,在循环结束后,它将使用i和v变量的当前值。
v将不再更改,循环结束时v == 3。我也= 3。但是你的委托将i写入输出,然后递增它(i ++)。因此,每次执行委托时,我都会增加,但不是v。
这是你所观察到的。
答案 3 :(得分:0)
我认为循环变量具有for循环外部的范围。
public static void Main(string[] args)
{
var funcs = new List<Func<string>>();
int i=0;
for(int v=0;v<3;v++,i++)
{
funcs.Add( new Func<string>(delegate(){return "Hello "+ i++ +" "+v;}) );
}
foreach(var f in funcs)
Console.WriteLine(f());
}
for循环i==3
和v==3
之后。由于代码不会在创建委托之间留下i
的范围,因此委托的所有三个实例共享相同的i
。因此,对函数的每次调用都会增加i
,3
,4
,5