Как удалить метод из делегата действия в C #

Возможный дубликат:
C # Добавление и Удаление анонимного обработчика событий

предположим, у меня есть делегат действия, объявленный следующим образом:

public event Action<MenuTraverser.Actions> menuAction;

Я связываю с ним метод таким образом:

menuInputController.menuAction += (MenuTraverser.Actions action) => this.traverser.OnMenuAction(action);

Теперь все работает нормально, но в определенной ситуации мне нужно удалить делегированный метод, и я не знаю, как это сделать. Я пробовал так, но не работает:

menuInputController.menuAction -= (MenuTraverser.Actions action) => this.traverser.OnMenuAction(action);

Как я могу это сделать? Мне нужно, чтобы мой метод OnMenuAction больше не вызывался.


person Heisenbug    schedule 11.12.2011    source источник
comment
Возможно, stackoverflow.com/questions/91778/?   -  person Matten    schedule 11.12.2011


Ответы (2)


Поскольку ваша подпись кажется совпадающей (при условии, что у вас есть тип возвращаемого значения void), вам не нужно добавлять анонимную функцию, но вы можете напрямую использовать группу методов:

menuInputController.menuAction += this.traverser.OnMenuAction;

И в этом случае должна работать и отписка:

menuInputController.menuAction -= this.traverser.OnMenuAction;
person Lucero    schedule 11.12.2011
comment
Я был бы рад, если это сработает, потому что, используя @sll, который работает, я вынужден иметь обработчик chached для каждого метода. В любом случае, мне кажется, что это не работает. - person Heisenbug; 11.12.2011
comment
Что вы имеете в виду под «кажется, не работает»? Обратите внимание, что -= вызывает Delegate.Remove, и это будет сравнить делегатов с помощью Delegate.Equals, в котором говорится следующее: возвращает true, если obj и текущий делегат имеет те же цели, методы и список вызовов - что имеет место в моем примере, но не тогда, когда у вас есть анонимные методы (которые различны, даже если в них один и тот же код). - person Lucero; 11.12.2011
comment
Я имею в виду, что если я воспользуюсь вашим решением, то делегат не будет удален. Может я что-то делаю не так, но просто заменяю свой код вашим, этого не происходит. И все же я ничего не понимаю: я использовал анонимные методы? - person Heisenbug; 11.12.2011
comment
menuAction использует код события по умолчанию или у него есть собственные обработчики add и remove? Потому что, если у него есть обработчики по умолчанию, мой код работает. И да, вы использовали анонимные методы: (MenuTraverser.Actions action) => this.traverser.OnMenuAction(action) (для этого варианта использования - потому что он не компилируется в lamdba-выражение) идентичен этому: delegate(MenuTraverser.Actions action) { this.traverser.OnMenuAction(action); }, который является анонимным методом. - person Lucero; 11.12.2011
comment
О .. ты прав. Ваш код работает (у меня была ошибка). И спасибо за разъяснения по анонимному методу. Я использовал их, даже не зная об этом. Значит, я поступал правильно, за исключением того, что использовал анонимные методы, верно? - person Heisenbug; 11.12.2011
comment
Кстати, есть ли документация по операторам -= и += для делегатов действий? Нигде не могу найти - person DataGreed; 08.08.2019
comment
@DataGreed Это языковая функция C #, а не фреймворк. Поэтому документы находятся на языковых страницах: docs .microsoft.com / en-us / dotnet / csharp / language-reference / и docs.microsoft.com/en-us/dotnet/csharp/language-reference/ - person Lucero; 08.08.2019

Вам нужно сохранить ссылку на общий делегат в поле, чтобы позже вы могли отказаться от подписки, используя это кешированное поле делегата:

// declare on a class fields level
Action<MenuTraverser.Action> cachedHandler; 

// in constructor initialize
cachedHandler = (action) => this.traverser.OnMenuAction(action);

// subscribe
menuInputController.menuAction += cachedHandler;

// unsubscribe
menuInputController.menuAction -= cachedHandler;
person sll    schedule 11.12.2011