Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当一个变量关闭两次时,它存储在哪里?_C#_.net_Lambda_Closures - Fatal编程技术网

C# 当一个变量关闭两次时,它存储在哪里?

C# 当一个变量关闭两次时,它存储在哪里?,c#,.net,lambda,closures,C#,.net,Lambda,Closures,我饶有兴趣地阅读了这篇文章,文章名为: 你看,C#编译器检测委托何时形成一个闭包,该闭包被传递出当前范围,并将委托和相关的局部变量提升到编译器生成的类中。这样,它只需要一些编译器技巧来传递编译器生成的类的实例,因此每次调用委托时,我们实际上是在调用该类上的方法 因此,本质上,一个封闭变量存储为匿名类的成员变量,该匿名类还包含表示lambda表达式的委托或在该变量上封闭的其他代码 如果是这种情况,当一个方法包含两个不同的lambda表达式,并且它们都引用相同的局部变量时,会发生什么情况 void

我饶有兴趣地阅读了这篇文章,文章名为:

你看,C#编译器检测委托何时形成一个闭包,该闭包被传递出当前范围,并将委托和相关的局部变量提升到编译器生成的类中。这样,它只需要一些编译器技巧来传递编译器生成的类的实例,因此每次调用委托时,我们实际上是在调用该类上的方法

因此,本质上,一个封闭变量存储为匿名类的成员变量,该匿名类还包含表示lambda表达式的委托或在该变量上封闭的其他代码

如果是这种情况,当一个方法包含两个不同的lambda表达式,并且它们都引用相同的局部变量时,会发生什么情况

void Test(IList list)
{
    int i = 0;

    list.Any( a => { Console.WriteLine("Lambda one says: {0}", i++); return true;} )
        .Any( a => { Console.WriteLine("Lambda two says: {0}", i++); return true;} );

}

我很确定我知道这里的行为。我的问题是,
i
到底存储在哪里?

该方法只有一个闭包类,而不是每个匿名方法都有一个闭包类。一个类将有两个实例方法和一个字段。该字段将存储
i
的值,这两个方法将分别对应于您的两个匿名方法。

FWIW,该代码不会编译
Any()
IEnumerable
的一个扩展方法,需要
Func
not
Action
@Cameron,除非他们有自己的
Console
类和返回布尔值的
WriteLine
方法。(还有他们自己的
Any
扩展方法,用于
IList
,因为LINQ
Any
方法不接受
IList
)。所有局部变量都存储在执行堆栈上。@jdweng这是完全错误的,这里显示的代码就是这样,它甚至包含了语言文档中的引号,解释了本地存储在哪里(以及它如何不在堆栈上)。如果变量需要存储在堆栈上,则闭包不可能工作,因为变量需要在方法完成后存在,如果变量存储在堆栈上,则闭包不可能工作。首先,内存必须在某个位置,局部变量必须放在堆栈上。其次,i不是lambda表达式的一部分,因此语言文档中的引用不适用。