What Func<;int,int>;表现得像这样

本文关键字:int 像这样 gt Func What lt | 更新日期: 2023-09-27 17:58:01

样品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的增量值?

What Func<;int,int>;表现得像这样

因为对于两个循环,i的最后一个值都是2。在第一个步骤中,不执行最后一步,因为循环条件评估为false,因为i变为2。这就是为什么y从未分配给2。在第二个片段中,lambda捕获i的最后一个值,即2,这就是它打印2的原因。

您正在将1传递给您的方法,但这并不重要。即使你传递了一个不同的值,你仍然会得到相同的结果。这一切都是关于闭包的。

如果你仍然有疑问,并且你想确定yi的最后一个值是什么,你可以做另一个简单的测试:

int y = 0;
for (int k = 0; k < 2; k++)
{
    y = k;
}
Console.WriteLine(y); // writes 1
int i = 0;
for(; i < 2; i++) { }
Console.WriteLine(i); // writes 2

在第二个样本中(实际上,在两个样本中),您创建了一个名为Closure的东西。每当您将变量用作lambda语句的一部分或在该lambda/委托之外定义的匿名委托时,都会创建闭包。此闭包捕获(关闭)for循环中的i变量,防止其"超出范围"。在脱离循环的条件失败之前,for循环必须最后一次递增i变量,使其变为2,因此最终使用2而不是1

第一个示例对y变量执行相同的操作。您仍然可以捕获/关闭变量并防止它超出范围。但是,y变量从未设置为2。该示例中的i变量仍然递增为2,但在此之后,代码不会进入循环,因此y永远不会设置为2,这样您仍然可以看到1的预期结果。

在这两种情况下,传递给该方法的1值都不会被使用,也没有任何效果。