考虑
Action _captureAction;
private void TestSimpleCapturedAction()
{
Action action = new Action(delegate { });
Action printAction = () => Console.WriteLine("Printing...");
action += printAction;
CaptureActionFromParam(action);
action -= printAction;
_captureAction(); //printAction will be called!
}
private void CaptureActionFromParam(Action action)
{
_captureAction = () => action();
}
_captureAction将调用printAction的原因是该行
action -= printAction;
实际上转化为
action = (Action) Delegate.Remove(action, printAction);
因此,CaptureActionFromParam()中_captureAction捕获的操作不会更改 - 只会影响TestSimpleCapturedAction()中的本地“action”变量。
在这种情况下我想要的行为是printAction没有被调用。我能想到的唯一解决方案是定义一个新的“委托容器”类:
class ActionContainer
{
public Action Action = new Action(delegate { });
}
private void TestCapturedActionContainer()
{
var actionContainer = new ActionContainer();
Action printAction = () => Console.WriteLine("Printing...");
actionContainer.Action += printAction;
CaptureInvoker(actionContainer);
actionContainer.Action -= printAction;
_captureAction();
}
private void CaptureInvoker(ActionContainer actionContainer)
{
_captureAction = () => actionContainer.Action();
}
这有效,但我想知道如果不引入这个新的抽象层,我是否可以实现我想要的行为。实施策略模式很容易导致这种情况,因此人们会认为语言和/或BCL会以某种方式本地支持它。
谢谢!
答案 0 :(得分:7)
代表就像字符串一样。它们被实现为引用类型,但它们的行为更像是不可变值类型。在字符串上添加或减去字符时,它不会更改字符串,它会生成一个新字符串作为新结果。当您从整数中添加或减去数字时,它不会更改整数,它会生成一个新结果,即新结果。当您从委托中添加或减少委托时,它不会更改委托;它会产生一个新的委托,这就是结果。
如果您想要捕获的是一个可以变化的委托,那么捕获一个包含对委托的引用的变量。变量变化,这就是为什么它们被称为“变量”。如果你想要变化的东西,可以得到变量。
CaptureActionFromParam(()=>{action();});
现在,捕获的委托本身捕获了变量“action”,而不是恰好位于其中的值。
记住:
有意义吗?