«Закрытие», созданное анонимной функцией, несколько отличается от того, что создано в других динамических языках (я буду использовать Javascript в качестве примера).
function thing() {
var o1 = {n:1}
var o2 = {dummy:"Hello"}
return function() { return o1.n++; }
}
var fn = thing();
alert(fn());
alert(fn());
Этот небольшой фрагмент javascript будет отображать 1, а затем 2. Анонимная функция может получить доступ к переменной o1, поскольку она существует в своей цепочке областей видимости. Однако анонимная функция имеет полностью независимую область видимости, в которой она может создать другую переменную o1 и тем самым скрыть любую другую дальше по цепочке областей действия. Также обратите внимание, что все переменные во всей цепочке остаются, следовательно, o2 будет продолжать существовать, сохраняя ссылку на объект до тех пор, пока переменная fn содержит ссылку на функцию.
Теперь сравните с анонимными функциями C #: -
class C1 { public int n {get; set;} }
class C2 { public string dummy { get; set; } }
Func<int> thing() {
var o1 = new C1() {n=1};
var o2 = new C2() {dummy="Hello"};
return delegate { return o1.n++; };
}
...
Func<int> fn = thing();
Console.WriteLine(fn());
Console.WriteLine(fn());
В этом случае анонимная функция не создает по-настоящему независимой области видимости больше, чем объявление переменной в любом другом блоке кода в функции {} (используется в foreach
, if
и т. Д.)
Следовательно, применяются те же правила, код вне блока не может получить доступ к переменным, объявленным внутри блока, но вы также не можете повторно использовать идентификатор.
Закрытие создается, когда анонимная функция передается вне функции, в которой она была создана. Отличие от примера Javascript состоит в том, что останутся только те переменные, которые фактически используются анонимной функцией, следовательно, в этом случае объект удерживается o2 будет доступен для GC, как только дело завершится,