Рекомендации по использованию лямбда-выражений для обработчиков событий

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

txtLogin.GotFocus += (o, e) =>
{
    txtLogin.Text = string.Empty;
    txtLogin.ForeColor = SystemColors.ControlText;
};
txtLogin.LostFocus += (o, e) =>
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

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

backgroundWorker.DoWork += (o, e) => DatabaseLookup.Open(e.Argument as string);

Я нашел некоторые аналогичные вопросы, касающиеся производительности и указывая, что вы не можете удалить их, но я не нашел адресации, простой вопрос о - это хорошая идея?

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

Ответ 1

Это вполне разумная идея - но в этом конкретном случае вместо этого я использовал бы анонимный метод:

txtLogin.LostFocus += delegate
{
    txtLogin.Text = "Login...";
    txtLogin.ForeColor = SystemColors.InactiveCaptionText;
};

Преимущество состоит в том, что вам не нужно указывать параметры, что делает его более понятным, чтобы вы их не использовали. Это единственное преимущество, которое анонимные методы имеют над лямбда-выражениями.

Достижение производительности почти всегда будет незначительным. Неспособность удалить их впоследствии является очень реальной проблемой, если вам нужно удалить обработчик, но я нахожу, что часто этого не происходит. (Reactive Extensions имеет хороший подход к этому - когда вы подписываетесь на наблюдаемую последовательность, вам возвращается IDisposable, которая удалит подписку, если вы ее назовете. Очень аккуратно.)

Ответ 2

Собственно, он считает, что он помещает обработчики событий в удобные для поиска места, а именно рядом с именем назначенного ему события.

В большинстве случаев вы увидите обработчики событий, например:

 void Text1_KeyDown(....) {....}

прикрепленный к событию KeyUp txtFirstName, потому что после использования Intellisense для создания обработчика кто-то решил переименовать текстовое поле и что KeyUp работал лучше. С помощью Lambda объект, событие и функция все вместе.

Ответ 3

Это сложный вопрос. Я помню, как читал в Code Complete о том, как некоторые (умные) люди говорят, что вы должны максимально контролировать поток управления, при этом многие спорят о точки входа и выхода из метода, потому что это не делает программу более трудной для выполнения.

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

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