A lambda expression can reference the local variables of the method in which it is defined. 
void DoStuff() 
{
  int factor = 2;
  Func<int, int> multiplier = x => x * factor;
}
In the above example, the outer variable factor is captured by the lambda multiplier.

A lambda expression that captures variables is called a closure.

An interesting fact about the closures is that the captured variables are evaluated when the delegate is actually invoked, not when the variables are captured.

For example, this code prints 333 to the console, instead of 012.
Action[] actions = new Action[3];

for (int i = 0; i < 3; i++)
{
    actions[i] = () => Console.WriteLine(i);
}

foreach (var action in actions)
{
    action();
}
Every time we create the new Action in the first for loop, it captures the same variable i.

However, it's only evaluated when when we actually invoke each action delegate. At that point, the value of the i is 3, as that was the final value that forced the control out of the loop. Hence it prints 3 three times.  

The above code can be re-written as follows, for a better understanding. 
Action[] actions = new Action[3];

int i = 0;
actions[0] = () => Console.Write(i);

i = 1;
actions[1] = () => Console.Write(i);

i = 2;
actions[2] = () => Console.Write(i);

i = 3;
foreach (var action in actions)
{
    action(); // 333
}




If we want the closure to print each value of i, we need to store it in a temporary variable. This variable will get created every time the loop runs, which forces the closure to capture the latest value of the i. 
Action[] actions = new Action[3];

for (int i = 0; i < 3; i++)
{
    int scoped = i;
    actions[i] = () => Console.WriteLine(scoped);
}

foreach (var action in actions)
{
    action();
}