【发布时间】:2015-01-15 01:31:10
【问题描述】:
更新: 原来这是 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”委托。不过,我似乎弄错了,因为这段代码似乎会导致在单击时重复调用相同的对话框,就像在递归函数中发生的那样(我猜这就是它变成的样子)。
我知道我可以,例如,在 for 循环中执行 int value = i;(其中 i 是循环迭代器)以在匿名函数中使用正确的 i 值(我在这)。代表似乎不同,但特别是什么使他们的工作方式不同?还是我做错了什么?我可以以类似的方式进行这种链接吗?我说“相似”是因为我当然可以考虑以其他更复杂的方式来做这件事......
注意:如果我对“关闭”、“代表”等词的使用不正确,请纠正我:)
【问题讨论】:
-
我知道这不是您要问的,但您似乎让这变得不必要地复杂了。既然你有一个循环,为什么不在循环中立即调用 ConfirmationDialog.Create() 。更少的代码,更少的复杂性。
-
因为这样会一次创建所有对话框,我需要每个对话框按顺序显示。它们具有一定的透明度,因此玩家会看到最前面的那些,这是不可取的。还有其他问题:)
-
这是从非 UI 线程创建对话框的问题吗?如果在 UI 线程上创建为模式对话框,您将一次看到一个(至少对于 WinForms 和 WPF...不确定您使用的是什么框架)。
-
哦,对不起,可能不太清楚,但我没有使用任何 C# 的 UI 框架。我正在使用 Unity3D 开发游戏。碰巧我使用 C# 作为语言。我会澄清这个问题。
-
无论是什么问题,它都是 Unity 和/或您的
ConfirmationDialog.Create()实现所特有的。 IE。似乎callback参数并没有像您认为的那样做。当我实现此代码的 WinForms 版本时,它完全符合我(和您)的期望:每个对话框都连续显示。确保您传递的callback参数实际上在用户关闭对话框之前不会被调用。您应该发布一个更完整的代码示例,其中包含ConfirmationDialog.Create()方法。见stackoverflow.com/help/mcve
标签: c# delegates closures anonymous-function