我试图掌握c#中闭包的概念。基本上尝试使用闭包捕获值和xBefore和yBefore
这是我的代码
int x = 0;
int y = 0;
Action PerformOperation(bool move, bool undo, int x1, int y1)
{
Action operationMove = null;
Action operationUndo = null;
int xBefore = 0;
int yBefore = 0;
operationMove = () =>
{
xBefore = x;
yBefore = y;
x = x1;
y = y1;
Debug.Log(" -- Move Operation -- " + " xBefore " +xBefore+ " yBefore " +yBefore+ " x " +x+ " y " +y);
};
operationUndo = () =>
{
x = xBefore;
y = yBefore;
Debug.Log(" -- Undo Operation -- " + " xBefore " +xBefore+ " yBefore " +yBefore+ " x " +x+ " y " +y);
};
if (move)
return operationMove;
if (undo)
return operationUndo;
return null;
}
然后在我的启动功能中调用Action
Action operation = PerformOperation (true,false,5,5);
operation ();
operation = PerformOperation (true, false, 15, 15);
operation ();
operation = PerformOperation (true, false, 30, 30);
operation ();
operation = PerformOperation (false, true, 10, 10);
operation ();
基本上,根据在PerformOperation中传递的布尔变量执行移动或撤消操作。所以xBefore和yBefore在通过operationMove操作更新之前跟踪x和y。 operationUndo以类似的方式调用,然后最终返回两个动作之一
前三次调用会正确跟踪xBefore和yBefore值。然而,最后一次撤消调用只返回所有0值,并且到目前为止还没有跟踪状态。我假设每次初始化操作= PerformOperatio(..)..创建一组新动作?
如何使用闭包正确实现基本撤消逻辑?
答案 0 :(得分:1)
每次调用声明了这些局部变量的方法时,闭包捕获的局部变量都会被有效地重新创建。你拥有的例子注定要失败,因为你只返回一个捕获了这些局部变量的最新实例的闭包。
在我看来,你应该做的是让方法本身执行操作,然后让方法返回{em>撤消刚刚完成的操作的Action
委托
例如,像这样:
Action PerformOperation(int x1, int y1)
{
int xBefore = x, yBefore = y;
x = x1; y = y1;
return () => { x = xBefore; y = yBefore; };
}
如果没有更完整的代码示例,我无法更具体。但我认为上面的内容更接近您对代码的期望。
然后,当您想要执行操作时,您可以调用该方法,并且当您想要撤消操作时,您将调用Action
代理执行操作时由方法返回的内容。
多级撤消/重做接口需要比上面更精细的处理,但它仍然基于相同的基本思想:捕获变量有多个实例,每次都有一个每个变量的实例该方法被称为。
答案 1 :(得分:1)
实际上,您可以略微更改代码,并将xBefore
和yBefore
从PerformOperation
移出。我认为它按预期工作。因此,当前值和旧值都在operationUndo
和operationMove
int x = 0;
int y = 0;
int xBefore = 0;
int yBefore = 0;
Action PerformOperation(bool move, bool undo, int x1, int y1)
{
Action operationMove = null;
Action operationUndo = null;
operationMove = () => ...