Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unexpected result when looping over List<Action>

I’m currently looking for tricky interview snippets and I found two that I cannot explain. I merged them together so they can be run at the same time.

Here is the code:

using System.Collections.Generic;
public class Program
{
    public static void Main(string[] args)
    {
        var intActions = new List<Action>();
        for (int i = 0; i < 4; i++)
            intActions.Add(() => { Console.WriteLine(i); });

        foreach (var action in intActions)
            action();


        string[] strings = { "abc", "def", "ghi" };
        var stringActions = new List<Action>();
        foreach (string str in strings)
            stringActions.Add(() => { Console.WriteLine(str); });

        foreach (var action in stringActions)
            action();
    }
}

The output is:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

4
4
4
4
abc
def
ghi

Can anyone explain me why is the result like this? I’d expect four "4"s with four "ghi"s or "0123" and "abc def ghi"

>Solution :

The reason why you are seeing 4444 and not 0123, & ghi ghi ghi instead of abc def ghi is due to closures.

The i variable passed to the delegate is passed by reference and not by value which means that all of the actions will point to the same memory location for variable i & the latest value for i (set to 4 on the last iteration of the loop).

For the output to be 0123, copying the variable to another temp variable would mean each action would have a pointer to a separate memory location, and thus yield the numbers as ‘expected’.

var intActions = new List<Action>();
for (int i = 0; i < 4; i++) {
    int copy = i;
    intActions.Add(() => { Console.WriteLine(copy); });
}

foreach (var action in intActions)
    action();

The same concept applies to the second part of your example:

string[] strings = { "abc", "def", "ghi" };
var stringActions = new List<Action>();
foreach (string str in strings) {
    var copy = str;
    stringActions.Add(() => { Console.WriteLine(copy); });
}

foreach (var action in stringActions)
    action();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading