什么Func <int,int>表现得像这样?</int,int>

时间:2014-04-13 04:49:54

标签: c#

样本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的值?

2 个答案:

答案 0 :(得分:2)

因为两个循环的i的最后一个值都是2。在第一个中,最后一步没有执行,因为循环条件计算为 false ,因为{{ 1}}变为2.这就是为什么i从未分配给y的原因。在第二个片段中,您的lambda捕获2的最后一个值i,这就是它打印2的原因。

您正在将2传递给您的方法,但这并不重要。即使您传递了不同的值,您仍然可以得到相同的结果。这就是closures

如果您仍然有疑问,并且想要确定1y的最后一个值,那么您可以进行另一个简单的测试:

i

答案 1 :(得分:0)

在您的第二个示例中(实际上,在两个示例中),您创建了一个名为 Closure 的内容。只要将变量用作lambda语句或在lambda / delegate之外定义的匿名委托的一部分,就会创建闭包。这个闭包捕获(关闭)i循环中的for变量,防止它超出范围&#34;。在突破循环的条件失败之前,for循环必须最后一次将i变量增加到2,因此您最终会使用2代替1

第一个示例与y变量做同样的事情。您仍然捕获/关闭变量并防止其超出范围。但是,y变量永远不会设置为2。该示例中的i变量仍然会增加到2,但在此之后代码不会进入循环,因此y永远不会设置为2,例如您仍然可以看到1的预期结果。

在这两种情况下,传递给方法的1值从未使用过,并且没有效果。