Являются ли лямбда-выражения в закрытии С#?

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

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

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

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

Ответ 1

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

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

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

int i = 42;

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

Это "закрытие" не "clojure".

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

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

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

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

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

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

Ответ 4

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