带有闭包的基本撤消/重做逻辑
本文关键字:重做 撤消 闭包 | 更新日期: 2023-09-27 17:57:53
我正在努力掌握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以类似的方式调用,然后最终返回两个操作之一
前3个移动调用正确跟踪xBefore和yBefore值。然而,最后一次调用undo只返回所有0值,并且到目前为止没有跟踪状态。我假设每次初始化操作=PerformOperatio(..)..时都会创建一组新的操作?
那么,我如何才能用闭包正确地实现基本的撤消逻辑呢?
每次调用声明局部变量的方法时,都会有效地重新创建闭包捕获的局部变量。您的示例注定会失败,因为您只返回一个捕获了这些局部变量的最新实例的闭包。
在我看来,你应该做的是让方法本身执行操作,然后让方法返回Action
委托,该委托将撤消刚刚完成的操作。
例如,类似这样的东西:
Action PerformOperation(int x1, int y1)
{
int xBefore = x, yBefore = y;
x = x1; y = y1;
return () => { x = xBefore; y = yBefore; };
}
如果没有一个更完整的代码示例,我就不能更具体了。但我认为以上内容更符合您对代码的期望。
然后,当您想执行操作时,您调用该方法,当您想要撤消该操作时,调用该方法在操作时返回的Action
委托。
多级undo/redo接口需要比上面更精细的处理,但它仍然基于相同的基本思想:捕获的变量有多个实例,每次调用方法时每个变量都有一个实例。
实际上,您可以稍微更改代码,将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 = () => ...