提前道歉,我可能会误用术语。我对闭包的概念有一些模糊的了解,但无法解释我观察到的行为。至少我认为这是一个闭包问题。我已经在网上搜索过,但没有找到正确的关键词来获取我想要的内容。
具体地说,我有两个代码块非常相似(至少在我的眼中)。首先:
static void Main(string[] args)
{
Action x1 = GetWorker(0);
Action x2 = GetWorker(1);
}
static Action GetWorker(int k)
{
int count = 0;
// Each Action delegate has it's own 'captured' count variable
return k == 0 ? (Action)(() => Console.WriteLine("Working 1 - {0}",count++))
: (Action)(() => Console.WriteLine("Working 2 - {0}",count++));
}
如果您运行此代码并调用x1()和x2()函数,您会发现它们维护了一个单独的“count”值。 foreach(var i in Enumerable.Range(0,4))
{
x1(); x2();
}
输出:
Working 1 - 0
Working 2 - 0
Working 1 - 1
Working 2 - 1
Working 1 - 2
Working 2 - 2
Working 1 - 3
Working 2 - 3
这对我来说很有道理,也符合我所读的解释。在幕后,为每个委托/动作创建一个类,并为该类提供一个字段来保存“计数”的值。我睡觉时感觉很聪明!
但是 - 然后我尝试了这段非常相似的代码:
// x3 and x4 *share* the same 'captured' count variable
Action x3 = () => Console.WriteLine("Working 3 - {0}", count++);
Action x4 = () => Console.WriteLine("Working 4 - {0}", count++);
就像评论所说的那样,这里的行为完全不同。x3()和x4()似乎具有相同的count值!
Working 3 - 0
Working 4 - 1
Working 3 - 2
Working 4 - 3
Working 3 - 4
Working 4 - 5
Working 3 - 6
Working 4 - 7
我可以看到正在发生的事情-但我真的不明白为什么他们被区别对待。在我脑海中,我喜欢我看到的最初的行为,但后来的例子让我感到困惑。希望这有意义。谢谢。
int count
变量声明(来自单独的方法调用)。你的第二个例子共享了相同的变量声明。如果int count
是你主程序的字段,你的第一个例子将与第二个例子行为相同。 - Chris Sinclair