【问题标题】:Scope and anonymous methods范围和匿名方法
【发布时间】:2013-09-24 14:28:33
【问题描述】:

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

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.

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

【问题讨论】:

  • 我认为编写的代码可能会在可能的并行操作完成之前调用Complete
  • @Kit,来自 Parallel.Invoke 的文档:This method does not return until each of the provided operations has completed, regardless of whether completion occurs due to normal or exceptional termination.
  • 哦,呵呵。我忘记了这个。谢谢提醒。

标签: c# scope anonymous-methods


【解决方案1】:

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

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

举个例子:

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"); }在同一个封闭类型中
猜你喜欢
  • 2010-10-22
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多