0

我有这个相当简单的逻辑:

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(),您会注意到当它在第一个语句上中断时,调试器将两者yts列为本地语句。但是当它在后者中遇到断点时,ts不会被列为本地,此外,添加ts到监视窗口会给出The name 'ts' does not exist in the current context.

这个变量是在起作用还是其他机制?我查看了有关变量捕获的文章,但找不到任何明确说明变量仅在使用时才被捕获的内容,但我假设它被称为变量捕获,因为它只“捕获”什么它需要并且不保留对所有可用内容的引用。

4

1 回答 1

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;
}

从这个示例中,您应该能够看到为什么封闭的字段是可访问的,而未从外部范围封闭的字段则不是。

于 2013-09-24T14:34:14.743 回答