#1,182 – Capturing a for Loop Variable in a Lambda Expression

If you capture a variable in a lambda expression that is declared within the initializer of a for loop, the results may not be what you expect.  Recall that the value of a captured variable is evaluated when a delegate is invoked, rather than when it is assigned.  If you therefore invoke the delegate after all iterations of the loop have executed, the value of the captured variable will be whatever the final value of the variable was.

Below, notice that the same value is displayed during each invocation of the delegate.

            Action[] dels = new Action[3];

            for (int i = 0; i < 3; i++)
                dels[i] = () => Console.WriteLine(i + 1);

            // Prints 4/4/4, rather than 1/2/3
            foreach (Action d in dels)
                d();

1182-001

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

2 Responses to #1,182 – Capturing a for Loop Variable in a Lambda Expression

  1. Pingback: Dew Drop – September 15, 2014 (#1855) | Morning Dew

  2. Stumbled upon you blog while redacting a micro-training for my team concerning lambdas in loops ;). Your explanations are great!
    And by the way, I also experimented with local functions (in loops) inside of lambdas. Behavior is the same (which I was expecting given I cast functions local to a loop into an array of actions, hence delegates…).
    What was less expected is Roslyn popping in to tell me I don’t need to introduce an intermediary variable which is ok inside a foreach, but not inside a for loop.
    May that interest you, here is my test:
    const int length = 10;
    var actions = new Action[length];
    for (var i = 0; i Console.Write($”{index} “);
    actions[i] = write;
    }
    foreach (var action in actions)
    action();

Leave a comment