C# 作用域和匿名方法

C# 作用域和匿名方法,c#,scope,anonymous-methods,C#,Scope,Anonymous Methods,我有一个相当简单的逻辑: class Program { static void Main(string[] args) { using (TransactionScope ts = new TransactionScope()) { System.Threading.Tasks.Parallel.Invoke(() => { Transactio

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

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
添加到监视窗口中会使
名称“ts”在当前上下文中不存在。

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

我假设它被称为变量捕获,因为它只“捕获”它需要的内容,而不保留对所有可用内容的引用

完全正确。编译器重构关闭变量的代码以使其保持在范围内。当使用匿名方法时,它不会关闭每个外部变量

以以下为例:

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;
}
从这个示例中,您应该能够看到为什么可以访问封闭的字段,而不可以访问外部作用域中未封闭的字段

我假设它被称为变量捕获,因为它只“捕获”它需要的内容,而不保留对所有可用内容的引用

完全正确。编译器重构关闭变量的代码以使其保持在范围内。当使用匿名方法时,它不会关闭每个外部变量

以以下为例:

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

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

添加没有捕获变量的lambda作为示例会更好
[CompilerGenerated]private void CompilerGeneratedName(){Debug.WriteLine(“Test”);}
在同一个封闭类型中添加lambda(不包含捕获的变量)作为示例会更好
[CompilerGenerated]private void CompilerGeneratedName(){Debug.WriteLine(“Test”);}
在同一类封闭类型中我认为编写的代码可能会在可能的并行操作完成之前调用
Complete
。@Kit,从docs for Parallel.Invoke:
此方法在提供的每个操作完成之前不会返回,无论完成是由于正常终止还是异常终止。
Oh duh。我忘了这个。谢谢提醒。我认为编写的代码可能会在可能的并行操作完成之前调用
Complete
。@Kit,来自用于并行的文档。Invoke:
此方法在提供的每个操作完成之前不会返回,无论完成是由于正常终止还是异常终止。
Oh duh。我忘了这个。谢谢你的提醒。