Lambda expressions will implicitly capture variables used and create a closure. A closure is a function along with some state context. The compiler will generate a closure whenever a lambda expression 'encloses' a value from its surrounding context.
E.g. when the following is executed
safeApplyFilterPredicate refers to a newly created object which has a private reference to the current value of
filterer, and whose
Invoke method behaves like
This can be important, because as long as the reference to the value now in
safeApplyFilterPredicate is maintained, there will be a reference to the object which
filterer currently refers to. This has an effect on garbage collection, and may cause unexpected behaviour if the object which
filterer currently refers to is mutated.
On the other hand, closures can be used to deliberate effect to encapsulate a behaviour which involves references to other objects.
Closures can also be used to model state machines:
Basic lambda expressions
Basic lambda expressions with LINQ
Lambda expressions with System.Linq.Expressions
Lambda syntax with statement block body
Using lambda syntax to create a closure
See remarks for discussion of closures. Suppose we have an interface:
and then the following is executed:
machineClosure refers to a function from
int, which behind the scenes uses the
IMachine instance which
machine refers to in order to carry out the computation. Even if the reference
machine goes out of scope, as long as the
machineClosure object is maintained, the original
IMachine instance will be retained as part of a 'closure', automatically defined by the compiler.
Warning: this can mean that the same function call returns different values at different times (e.g. In this example if the machine keeps a sum of its inputs). In lots of cases, this may be unexpected and is to be avoided for any code in a functional style - accidental and unexpected closures can be a source of bugs.