捕获变量时,会创建一个包装类
例子:
1: static void Main(string[] args) 2: { 3: Console.WriteLine("Variable Capturing"); 4: 5: string name = "Matthew"; 6: Func<String> capture = () => name; 7: 8: name = "Mallory"; 9: 10: Print(capture); 11: 12: } 13: 14: static void Print(Func<string> capture) 15: { 16: Console.WriteLine(capture()); 17: }
变量“name”在第 6 行的 lambda 表达式内被捕获。然后在第 8 行修改相同的变量。然后在第 10 行,我们将 lambda 表达式传递给 Print 函数,然后打印出捕获的变量。当代码运行时,输出将是:
Mallory
值得注意的是,虽然变量“name”在第 6 行被“捕获”,但它反映了第 8 行对局部变量“name”所做的更改。要了解它是如何工作的,让我们展示一下 C# 编译器将大致变成什么之前的代码进去。(我将匿名类型的名称更改为更具可读性):
1: public class Capture 2: { 3: public string name; 4: 5: public string Lambda() 6: { 7: return this.name; 8: } 9: 10: } 11: 12: static void Main(string[] args) 13: { 14: Capture capture = new Capture(); 15: 16: Console.WriteLine("Variable Capturing"); 17: 18: capture.name = "Matthew"; 19: 20: capture.name = "Mallory"; 21: 22: Print(capture.Lambda); 23: } 24: 25: static void Print(Func<string> capture) 26: { 27: Console.WriteLine(capture()); 28: }
创建了一个名为“Capture”的新类。原始代码中所有出现的变量“name”都被替换为对捕获类的“name”成员的字段访问。此外,lambda 表达式变成了我称之为 Lambda 的捕获类上的一个方法(是的,这就是所有匿名委托和 lambda 表达式)。这就是变量的更改如何在 lambda 表达式中持久化,对变量的每次更改只会修改 Capture 类中的字段。

