简短的回答:没有。.NET 不需要遍历作用域链来查找变量。
长答案:
从这个例子开始:
static Func<string> CaptureArgs(int a, int b)
{
return () => String.Format("a = {0}, b = {1}", a, b);
}
static void Main(string[] args)
{
Func<string> f = CaptureArgs(5, 10);
Console.WriteLine("f(): {0}", f());
// prints f(): a = 5, b = 10
}
在CaptureArgs方法中,a并存b在于栈上。直观地说,如果我们在匿名函数中引用变量,则返回该函数并弹出堆栈帧应该从内存中删除a和。b(这称为向上的函数参数问题)。
C# 不会遇到向上的函数参数问题,因为在幕后,匿名函数只是编译器生成的类的花哨语法糖。上面的 C# 代码变成:
private sealed class <>c__DisplayClass1
{
// Fields
public int a;
public int b;
// Methods
public string <CaptureArgs>b__0()
{
return string.Format("a = {0}, b = {1}", this.a, this.b);
}
}
编译器创建并返回 的一个新实例<>c__DisplayClass1,从 初始化它的a和b字段a并将其b传递给方法(这实际上将和从堆栈CaptureArgs复制到堆上存在的字段),并将其返回给调用者。呼唤真的是呼唤。abf()<>c__DisplayClass1.<CaptureArgs>b__0()
由于a和b引用的<CaptureArgs>b__0是普通字段,它们可以由委托直接引用,它们不需要任何特殊类型的范围链接规则。