匿名方法(lambda)中捕获的外部变量

时间:2014-03-28 17:02:50

标签: c# .net lambda


我刚读了MSDN,发现这里有什么需要建议 http://msdn.microsoft.com/en-us/library/0yw3tz5k.aspx

  

创建委托时,对外部变量n的引用被称为捕获。与局部变量不同,捕获的变量的生命周期会延长,直到引用匿名方法的委托符合垃圾回收的条件。

“捕获”是否意味着它将按值复制? 但是我尝试编写一个示例程序如下:

class Program
{

    class async_class
    {
        private int n = 0;

        public async_class()
        {
            for (int i = 0; i <= 9; i++)
            {
                System.Console.WriteLine("Outer  n={0} address={1}", n, n.GetHashCode());
                System.Threading.Thread thread1 = new System.Threading.Thread( () =>
                {
                    System.Console.WriteLine("Inner after n={0} address={1}", ++n, n.GetHashCode());
                });
                thread1.Start();
                //n = 10;
            }

        }

    }

    static void Main(string[] args)
    {
        async_class class1 = new async_class();
     }
}
}

在此示例中,内部“++ n”将写回原始外部“n”。结果将是。

  

外部n = 0地址= 0
  外n = 0地址= 0
  内部在n = 1地址= 1之后   外n = 1地址= 1

任何人都可以解释有关“捕获”外部变量的更多细节吗?

1 个答案:

答案 0 :(得分:4)

不,说它被捕获的全部意义在于它只是复制值。闭包关闭变量,而不是。程序中n的每次访问都访问同一个变量,从来没有任何副本。

那就是说,你的程序是这个案例的一个令人困惑的例子;它正在使用多个线程,这会引入各种竞争条件,因为您无法安全地操纵多个线程中的变量。这将导致各种未定义的行为。如果你想研究闭包,可以从单个线程中学习;它会使你的程序更容易理解,很多

您可以编写很多更简单的程序来证明闭包关闭变量而不是值。这是一个简单的代码段:

int n = 2;
Action a = () => Console.WriteLine(n);
n = 5;
a();

如果闭包捕获了n的值,则会打印2.如果它关闭变量而不是,它将打印5继续运行它,看看会发生什么。