лямбда-выражения в C #? - PullRequest
       15

лямбда-выражения в C #?

2 голосов
/ 12 марта 2010

Я довольно новичок в этом, кто-то может объяснить значение (следующего кода) или, возможно, дать ссылку на некоторую полезную информацию о лямбда-выражениях? Я сталкиваюсь со следующим кодом в тесте, и мне интересно, почему кто-то сделал бы это:

foo.MyEvent += (o, e) => { fCount++; Console.WriteLine(fCount); };

foo.MyEvent -= (o, e) => { fCount++; Console.WriteLine(fCount); };

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

Ответы [ 6 ]

10 голосов
/ 12 марта 2010

Лямбда-выражение (o, e) => { fCount++; Console.WriteLine(fCount); } интерпретируется как анонимный метод , который принимает два аргумента o, e (типы которых выводятся из типа делегата, используемого для MyEvent, и возвращает void. It захватывает переменную fCount в теле метода включения (если это локальная переменная). Оператор += подпишет анонимный метод на событие, а -= отписывает делегата от события.


Обновление (касательно равенства экземпляров делегатов):

Важно знать, что не стоит пытаться отписаться от этого события. Спецификация языка разрешает, но не требует, чтобы делегат во второй строке был равен делегату из первой строки. То есть компилятору разрешается обрабатывать два тела анонимных функций так, как если бы это была одна и та же функция или нет (потому что тело анонимной функции семантически идентично и набор захваченных переменных также равен). Даже если он работает так, как ожидается в вашем компиляторе, он может сломаться в следующей версии. Процитируем Спецификацию языка C # на этом:

Спецификация языка C # (раздел 7.9.8 Делегировать операторы равенства):

Записи списка вызовов, полученные из оценки семантически идентичных выражений анонимных функций с тем же (возможно, пустым) набором захваченных экземпляров внешней переменной, разрешены (но не обязательны) равными.

Если компилятор обрабатывает два выражения анонимной функции как равные, вторая строка отписывает предыдущий анонимный метод от события. Если этого не произойдет, вторая строка не будет делать ничего особенного (это не ошибка - отписаться от делегата из списка вызовов событий, если его еще нет в списке).

2 голосов
/ 12 марта 2010

Здесь - отличное видео о лямбда-выражениях в C #. Этому видео уже 2 года, но оно позволяет пользователям быстрее освоить функциональность, которая была относительно новой в то время. Интересующий вас контент начинается около 3: 02.

1 голос
/ 12 марта 2010

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

0 голосов
/ 12 марта 2010

Лямбда-выражения являются синтаксическим сокращением для объявления функции. Таким образом,

(o, e) => { fCount++; Console.WriteLine(fCount); }

означает функцию, которая принимает два аргумента и выполняет два оператора.

Что касается фрагмента кода, отмена подписки '- =' не будет работать, потому что это сокращение для:

foo.MyEvent += new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent -= new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );

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

var handler = new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent += handler;
foo.MyEvent -= handler;
0 голосов
/ 12 марта 2010

Похоже, он думает, что это эквивалентно:

var eh = new EventHandler(delegate(object o, EventArgs e)
    { fCount++; Console.WriteLine(fCount); };

foo.MyEvent += eh;

foo.MyEvent -= eh;

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

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

0 голосов
/ 12 марта 2010

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

...