在匿名方法(lambda)中捕获的外部变量
本文关键字:外部 变量 方法 lambda | 更新日期: 2023-09-27 17:54:46
我刚读了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
有人可以解释"捕获">外部变量的更多细节吗?
不,说它被捕获的全部意义在于它是而不是只是复制值。闭包关闭变量,而不是值。程序中n
的每一次访问都在访问同一个变量,从来没有任何副本。
也就是说,你的程序是一个令人困惑的例子;它使用了多个线程,并且引入了各种竞争条件,因为您无法从多个线程安全地操作变量。这将导致各种未定义的行为。如果你想研究闭包,可以从一个线程开始;它将使你的程序更容易推理。
您可以编写更简单的程序来证明闭包关闭在变量上,而不是值上。这里有一个简单的片段:
int n = 2;
Action a = () => Console.WriteLine(n);
n = 5;
a();
如果闭包捕获了n
的值,则会打印2。如果它关闭变量而不是其值,它将打印5。继续运行它,看看会发生什么。