Enqueue various method calls with parameters

For a game in which you have to code your own AI, I need to enqueue various method calls with parameters. For example:

MessageReceived(string text, Source source);
MiningCompleted(ResourceData data);

This has to be done, to call all Events at the beginning of the next step of the game and not instantly. Now I have written a small prove of concept for passing parameters to the methods:

namespace LambdaTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Queue<Action> q = new Queue<Action>();

            for (int i = 0; i < 5; i++)
            {
                q.Enqueue(new Action(() => {
                    // Methods should be called here
                    Console.WriteLine(i);
                }));
            }

            foreach (Action a in q)
                a();

            Console.ReadLine();
        }
    }
}

The first thought was it has to work. After seeing the output of 5x5 my question was, why doesn't it output 0 to 4 and why does it actually work, because i doesn't exist in this scope anymore.

  1. Why does it output 5x5?
  2. How can I enqueue different method calls with parameters this way?
Jon Skeet
people
quotationmark

It outputs 5 five times because by the time you're executing the actions, i is 5. There's only a single i variable, and its lifetime is extended until all anonymous functions that have captured it are eligible for garbage collection.

To fix this, just introduce a separate variable inside the loop which takes a copy of the loop variable:

for (int i = 0; i < 5; i++)
{
    // Declared *inside* the loop, so each iteration will have a separate variable
    int copy = i;
    q.Enqueue(() => Console.WriteLine(copy));
}

people

See more on this question at Stackoverflow