foreach循环内的匿名函数中的委托没有闭包

时间:2014-11-18 00:26:51

标签: c# delegates closures anonymous-function

UPDATE:结果证明这是Unity3D使用的Mono编译器的问题。我不确定当前版本的Mono(3.10.0)是否修复了它,但引擎中使用的旧版本(2.0.5)似乎没有为代表实现此功能,或者只是按照它应该工作。


在我正在开发的游戏中(在Unity3D引擎中),玩家可以同时解锁多个项目。对于他们每个人,我必须提供一个简单的信息对话框,用户必须单击该对话框才能前进到下一个,直到所有内容都已被阅读。

我有一个简单的C#静态方法来显示一个对话框(只是一个带有Unity中某些文本的彩色叠加层,而不是与C#UI框架有任何关系):

ConfirmationDialog.Create("Item X Unlocked!", callback);

当用户最后按下对话框时,会调用callback

我想链接所有对话框,以便每个对话框都只在点击上一个时创建,所以我尝试了这个:

Action callback = delegate {};

foreach (string item in unlockedItems) {
    var cb = callback;  // I though this would create a closure for delegates too
    callback = (() => ConfirmationDialog.Create(item + " Unlocked!", cb));
}
callback();

这在我的脑海中是有意义的,因为匿名函数将在循环的每次迭代中使用不同的“cb”委托。但是,我似乎错了,因为这个代码似乎导致同一个对话框在被点击时被重复调用,就像在递归函数中发生的那样(我猜它是什么)。 / p>

我知道我可以,例如,在for循环中执行int value = i;(其中i是循环迭代器)在匿名函数中使用正确的i值(I发现了很多这方面的材料)。代表们似乎有所不同,但具体是什么使他们不能以同样的方式工作?或者我在做一些非常错误的事情?我可以用类似的方式进行链接吗?我说“相似”,因为我当然可以想到用其他更复杂的方式来做这件事......

注意:如果我使用“封闭”,“委托”等字样,请纠正我:)

1 个答案:

答案 0 :(得分:1)

您是否可以控制ConfirmationDialog.Create("Item X Unlocked!", callback); API?如果是这样,您应该考虑重构使用Task而不是回调。如果你有这个,你可以简单地将一堆任务链接为延续,并让它们一个接一个地执行。

我知道在游戏开发方面,这些东西本质上是非常异步的,UI的显示方式以及随后的反应...所以你可以使用TaskCompletionSource,这样你就可以处理一些信号你的任务已经完成。