样本1:
static void DelegateTest()
{
Func<int, int> test = null;
for(int i=0;i<2;i++)
{
int y = i;
test = (t) => y;
}
Console.WriteLine(test(1)); // This thing prints 1
//Console.ReadLine();
}
样本2:
static void DelegateTest2()
{
Func<int, int> test = null;
for (int i = 0; i < 2; i++)
{
test = (t) => i;
}
// This thing prints 2. I want to know why?
//Because 'i' gets out of scope when test(1) gets called and it should print 1
Console.WriteLine(test(1));
Console.ReadLine();
我想知道为什么当我们在范围外调用它时,Func会增加i的值?
答案 0 :(得分:2)
因为两个循环的i
的最后一个值都是2
。在第一个中,最后一步没有执行,因为循环条件计算为 false ,因为{{ 1}}变为2.这就是为什么i
从未分配给y
的原因。在第二个片段中,您的lambda捕获2
的最后一个值i
,这就是它打印2的原因。
您正在将2
传递给您的方法,但这并不重要。即使您传递了不同的值,您仍然可以得到相同的结果。这就是closures。
如果您仍然有疑问,并且想要确定1
和y
的最后一个值,那么您可以进行另一个简单的测试:
i
答案 1 :(得分:0)
在您的第二个示例中(实际上,在两个示例中),您创建了一个名为 Closure 的内容。只要将变量用作lambda语句或在lambda / delegate之外定义的匿名委托的一部分,就会创建闭包。这个闭包捕获(关闭)i
循环中的for
变量,防止它超出范围&#34;。在突破循环的条件失败之前,for
循环必须最后一次将i
变量增加到2
,因此您最终会使用2
代替1
。
第一个示例与y
变量做同样的事情。您仍然捕获/关闭变量并防止其超出范围。但是,y
变量永远不会设置为2
。该示例中的i
变量仍然会增加到2
,但在此之后代码不会进入循环,因此y
永远不会设置为2
,例如您仍然可以看到1
的预期结果。
在这两种情况下,传递给方法的1
值从未使用过,并且没有效果。