我有这个相当简单的逻辑:
class Program
{
static void Main(string[] args)
{
using (TransactionScope ts = new TransactionScope())
{
System.Threading.Tasks.Parallel.Invoke(() =>
{
TransactionScope y = ts;
System.Diagnostics.Debug.WriteLine("Test");
},
() =>
{
System.Diagnostics.Debug.WriteLine("Test");
}
);
ts.Complete();
}
}
}
如果您在两个Debug.WriteLine()
语句中放置断点,您会注意到,当它在第一个语句中断时,y
和ts
都会被调试器列为本地语句。但当它遇到后者的断点时,ts
未列为本地,此外,在观察窗口中添加ts
会产生The name 'ts' does not exist in the current context.
这个变量是在捕获还是其他一些机制?我已经查看了关于变量捕获的文章,我找不到任何明确说明变量只在被使用时被捕获的东西,但是我假设它被称为变量捕获,因为它只是“捕获”了什么它需要并且不会保留对所有可用内容的引用。
答案 0 :(得分:3)
我假设它被称为变量捕获因为它只捕获"它需要什么,并没有引用所有可用的东西
这完全正确。编译器重构关闭变量的代码以使其保持在范围内。当使用匿名方法时,它不会关闭每个外部变量。
采用以下示例:
public static void Foo()
{
int i = 0;
int j = 1;
Action a = () => Console.WriteLine(i);
}
编译器会将其变成类似的内容:
public class ClosureClass1
{
public int i;
public void Method1()
{
Console.WriteLine(i);
}
}
public static void Foo()
{
ClosureClass1 closure = new ClosureClass1();
closure.i = 0;
int j = 1;
Action a = closure.Method1;
}
从这个例子中,您应该能够看到为什么可以访问已关闭的字段以及未从外部范围关闭的字段。