我正在阅读lambda表达式,我已经看过这个例子,
例1:
static Func<int> Natural()
{
int seed = 0;
return () => seed++; // Returns a closure
}
static void Main()
{
Func<int> natural = Natural();
Console.WriteLine (natural()); // output : 0
Console.WriteLine (natural()); // output : 1
}
Run Code Online (Sandbox Code Playgroud)
例2:
static Func<int> Natural()
{
return() => { int seed = 0; return seed++; };
}
static void Main()
{
Func<int> natural = Natural();
Console.WriteLine (natural()); // output : 0
Console.WriteLine (natural()); // output : 0
}
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么第一个示例输出是0和1.
因为第二个example(int seed = 0)中的初始化代码是在每次调用时运行的.
在第一个示例中,seed是一个捕获的变量,它存在于方法之外,因为在调用之间只保留一个实例.
更新:回应David Amo的评论,解释.
选项1)
static Func<int> Natural()
{
int seed = 0;
return () => seed++; // Returns a closure
}
Run Code Online (Sandbox Code Playgroud)
选项2)
static Func<int> Natural()
{
return() => { int seed = 0; return seed++; };
}
Run Code Online (Sandbox Code Playgroud)
选项3)
static Func<int> Natural()
{
int seed = 0;
return () => { seed = 0; return seed++;}; // Returns a closure
}
Run Code Online (Sandbox Code Playgroud)
选项3返回与选项2相同的值,但内部作为选项1使用.seed是内部定义的变量Natural,但由于它由委托捕获,因此在方法退出后继续存在.
您可以用来查看正在发生的事情的另一个测试是
static Func<int> Natural()
{
int seed = 1;
Func<int> returnValue = () => { return seed++; };
seed = 2;
return returnValue;
}
Run Code Online (Sandbox Code Playgroud)
lambda 表达式可以引用定义它的方法的局部变量和参数(外部变量)
\n\nlambda 表达式引用的外部变量称为捕获变量。捕获变量的 lambda 表达式称为闭包。
\n\n捕获的变量在实际调用委托时计算,而不是在捕获变量时计算:
\n\nint factor = 2;\nFunc<int, int> multiplier = n => n * factor;\nfactor = 10;\nConsole.WriteLine (multiplier (3)); // 30\nRun Code Online (Sandbox Code Playgroud)\n\nLambda 表达式本身可以更新捕获的变量:
\n\nint seed = 0;\nFunc<int> natural = () => seed++;\nConsole.WriteLine (natural()); // 0\nConsole.WriteLine (natural()); // 1\nConsole.WriteLine (seed); // 2\nRun Code Online (Sandbox Code Playgroud)\n\n捕获的变量的生命周期延长到委托的生命周期。在下面的示例中,当 Natural 完成执行时,局部变量种子通常会从作用域中消失。但由于种子已被捕获,因此它的生命周期自然会延长到捕获委托的生命周期:
\n\nstatic Func<int> Natural()\n{\n int seed = 0;\n return () => seed++; // Returns a closure\n}\n\nstatic void Main()\n{\n Func<int> natural = Natural();\n Console.WriteLine (natural()); // 0\n Console.WriteLine (natural()); // 1\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在 lambda 表达式中实例化的局部变量在每次调用委托实例时都是唯一的。如果我们重构前面的示例以在 lambda 表达式中实例化种子,我们会得到不同的(在本例中是不希望的)结果:
\n\nstatic Func<int> Natural()\n{\n return() => { int seed = 0; return seed++; };\n}\n\nstatic void Main()\n{\n Func<int> natural = Natural();\n Console.WriteLine (natural()); // 0\n Console.WriteLine (natural()); // 0\n}\nRun Code Online (Sandbox Code Playgroud)\n