让我提前道歉 - 我可能在使用术语。我对什么是闭包有一个模糊的理解,但无法解释我所看到的行为。至少,我认为这是一个关闭问题。我在网上搜索过,但没有找到合适的关键字来获得我想要的内容。
具体来说——我有两个非常相似的代码块(至少在我看来是这样)。第一:
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(),您会看到它们维护着一个单独的“计数”值。
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
这对我来说很有意义,并且与我读过的解释相符。在幕后,为每个委托(delegate)/ Action 创建一个类,并为该类提供一个字段来保存“计数”的值。我上床 sleep 时感觉很聪明!
但是然后 - 我尝试了这个非常相似的代码:
// 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() 似乎具有相同的计数值!
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
是主程序的一个字段,您的第一个示例将与第二个示例的行为相同:
static int count = 0;
static Action GetWorker(int k)
{
return k == 0 ? (Action)(() => Console.WriteLine("Working 1 - {0}",count++))
: (Action)(() => Console.WriteLine("Working 2 - {0}",count++));
}
这个输出:
Working 1 - 0
Working 2 - 1
Working 1 - 2
Working 2 - 3
Working 1 - 4
Working 2 - 5
Working 1 - 6
Working 2 - 7
你也可以在没有三元运算符的情况下简化它:
static Action GetWorker(int k)
{
int count = 0;
return (Action)(() => Console.WriteLine("Working {0} - {1}",k,count++));
}
哪些输出:
Working 1 - 0
Working 2 - 0
Working 1 - 1
Working 2 - 1
Working 1 - 2
Working 2 - 2
Working 1 - 3
Working 2 - 3
主要问题是方法中声明的局部变量(在您的例子中是int count = 0;
)对于那个调用是唯一的> 方法,然后在创建 lambda 委托(delegate)时,每个委托(delegate)都围绕其自己唯一的 count
变量应用闭包:
Action x1 = GetWorker(0); //gets a count
Action x2 = GetWorker(1); //gets a new, different count
关于c# - 为什么有些闭包比其他的闭包 'Friendlier'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23527682/