Являются ли лямбда-выражения в C # замыканиями? - PullRequest
56 голосов
/ 07 марта 2012

Являются ли лямбда-выражения (и в некоторой степени анонимными функциями) замыканиями?

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

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

Спасибо за любые разъяснения, которые вы можете предоставить!

Ответы [ 4 ]

107 голосов
/ 07 марта 2012

Лямбда может быть реализована с использованием замыкания, но оно не обязательно само по себе замыкание.

A closure - это «функция вместе со ссылочной средой для нелокальных переменных этой функции.».

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

int i = 42;

Action lambda = () => { Console.WriteLine(i); }; 

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

Однако эта лямбда:

Action lambda2 = () => { Console.WriteLine("Foo"); }

не полагается на какую-либо "среду обращения", поскольку это полностью автономный метод. В этом случае компилятор генерирует обычный статический метод, и замыкание вообще не используется.

В обоих случаях лямбда создает delegate («объект функции»), но в первом случае это только замыкание, поскольку лямбда не обязательно должна «захватывать» среду ссылок во всех случаи.

71 голосов
/ 07 марта 2012

Рид ответ правильный;Я просто добавил бы несколько дополнительных деталей:

  • лямбда-выражения и анонимные методы оба имеют семантику замыкания;то есть они «захватывают» свои внешние переменные и увеличивают время жизни этих переменных.

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

  • функция, которую можно рассматривать как объект, является просто делегатом.Что делает лямбду замыканием , так это то, что она захватывает свои внешние переменные.

  • лямбда-выражения, преобразованные в деревья выражений, также имеют семантику замыкания, что довольно интересно.И реализация этого правильно была болью в шее, я вам говорю!

  • «this» считается «внешней переменной» с целью создания замыкания, даже если «this»не переменная.

12 голосов
/ 07 марта 2012

Это «замыкание», а не «замыкание».

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

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

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

Когда вы говорите

функции, которые рассматриваются как объекты,

это обычно просто "функцияобъект "(в C # мы бы сказали" делегат ") и часто встречается в функциональном программировании.

8 голосов
/ 07 марта 2012

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

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