Рассмотрим
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();
}
Причиной вызова функции printAction _captureAction является то, что строка
action -= printAction;
На самом деле переводится как
action = (Action) Delegate.Remove(action, printAction);
поэтому действие, захваченное _captureAction в CaptureActionFromParam (), не изменяется - затрагивается только локальная переменная 'action' в TestSimpleCapturedAction ().
Мое желаемое поведение в таком сценарии было бы, чтобы 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 каким-то образом поддержат его.
Спасибо!