метод подписки против подписки на лямбда-делегатов - что и почему? - PullRequest
5 голосов
/ 31 августа 2010

Я видел, как некоторые люди полагались на передачу методов обратным вызовам / событиям, а затем иногда просто передавали им лямбды.

Может ли кто-нибудь говорить о какой-либо разнице между этими двумя понятиями?Первоначально я думал бы, что они одинаковы, но несоответствие, которое я видел реализованным, иногда заставляет задуматься, есть ли случай, когда один предпочтительнее другого?Очевидно, что если количество кода очень велико, оно не должно быть на месте лямбда, но в противном случае ...

Можете ли вы все изложить какие-либо различия между ними, если они есть, и наметить правила, которые вы используетевыбирать между двумя, когда оба доступны?

Ответы [ 4 ]

7 голосов
/ 31 августа 2010

Одним из самых больших различий между ними является легкость, с которой вы можете отказаться от подписки на событие. С подходом, основанным на методе, отмена подписки является простой операцией, просто используйте оригинальный метод

m_button.Click += OnButtonClick; 
...
m_button.Click -= OnButtonClick;

С лямбдами это не так просто. Вы должны сохранить лямбда-выражение и использовать его позже, чтобы отписать от события

m_button.Click += delegate { Console.Write("here"); }
...
// Fail
m_button.Click -= delegate { Console.Write("here"); } 

EventHandler del = delegate { Console.Write("here"); }
m_button.Click += del;
...
m_button.Click -= del;

Это действительно умаляет удобство использования лямбда-выражений.

2 голосов
/ 31 августа 2010

В большинстве языков с лямбдами (включая C #) создание лямбды внутри метода создает замыкание, то есть локальные переменные внутри объявленного метода будут видны лямбда-выражению.Это самое большое различие, о котором я знаю.

Кроме того, если вы не назовете свой обработчик событий каким-либо способом, доступным в другой функции, вам будет трудно отсоединить обработчик событий позже.Это можно сделать, сохранив делегат в переменной уровня экземпляра или класса, но это может быть довольно уродливо.

1 голос
/ 31 августа 2010

Самая большая причина для использования лямбды - это задержка выполнения, т.е. вы определяете операции, которые хотите выполнить, но у вас не будет параметров позже.Вы обычно не используете лямбды для событий и обратных вызовов;вы используете анонимные методы.

Использование анонимных методов для событий и обратных вызовов - это нормально для простых событий, на которые вам не нужно отписываться.Самый большой определяющий фактор для меня - то, где я заявляю это.Я не собираюсь объявлять обработчик событий для формы как анонимный метод, но если у меня есть недолгая необходимость подключения к событию, это может быть нормально.

В общем, я использую фактическийметоды для обратных вызовов и событий больше, чем анонимные методы;события, с которыми я работаю, связаны с временем жизни объекта, а не с временем жизни метода, и я обнаружил, что в коде яснее иметь обратные вызовы, четко определенные вне функции, которая их подключает.Отчасти это личное предпочтение.

0 голосов
/ 23 мая 2016

В большинстве случаев практическая разница невелика.Какой из них использовать, в основном, зависит от личных предпочтений (т.е. от того, что вы хотите, чтобы код выглядел как).В некоторых случаях есть несколько практических причин отдавать предпочтение одному из других:

  1. Как отмечено в принятый ответ , отмена анонимного метода более сложна, чем отмена именованного метода,Без имени невозможно ссылаться на анонимный метод, кроме как с помощью экземпляра делегата, созданного во время выполнения, когда анонимный метод объявлен.Используя именованный метод, делегат может быть отписан без сохранения ссылки на исходный делегат (или его эквивалент).
  2. С другой стороны, причина предпочитать лямбда-выражение - это когда обработчик событияэто деталь реализации, уникальная для именованного метода, в которой объявлен лямбда / анонимный метод.Это может помочь сохранить такие детали реализации частными и локальными для метода, в котором они используются.
  3. Еще одна причина, по которой можно использовать лямбда-выражение, - это необходимость «адаптировать» тип делегата.Т.е. вы хотите вызвать именованный метод для обработки события, но этот метод имеет подпись, отличную от той, которая требуется для события.Это может быть тот случай, когда вы хотите повторно использовать метод для других событий или других ситуаций, когда некоторые параметры из события могут быть неприменимы.В другом случае вам может потребоваться ввести новый параметр, значение которого может не предоставляться событием (например, индекс для коллекции объектов, имеющих все то же событие, на которое вы хотите подписаться).

Иногда может возникнуть один особый случай, который заключается в выборе того, использовать ли именованный метод сам по себе или использовать анонимный метод, который затем вызывает этот именованный метод.Важно отметить, что при отсутствии других практических причин для выбора одного из других использование именованного метода незначительно более эффективно , в данном конкретном случае , поскольку оно удаляет один вызов метода из вызова.На практике вы, вероятно, никогда не заметите разницу, но это просто накладные расходы, поэтому, если нет конкретной практической причины для ее возникновения, вероятно, следует избегать ее, то есть напрямую подписывать именованный метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...