“ClosureAndForeach” (Solution)

Answer

In old compiler versions: 3 3 3.
In new compiler versions: 1 2 3.

Explanation

In old compiler versions, the code from the problem will be transformed in the following code:
1
public void Run()
2
{
3
var actions = new List<Action>();
4
DisplayClass c1 = new DisplayClass();
5
foreach (int i in Enumerable.Range(1, 3))
6
{
7
с1.i = i;
8
list.Add(c1.Action);
9
}
10
foreach (Action action in list)
11
action();
12
}
13
14
private sealed class DisplayClass
15
{
16
public int i;
17
18
public void Action()
19
{
20
Console.WriteLine(i);
21
}
22
}
Copied!
Thus, all elements from the list refer to same delegate. So, we will see 3 same values in the console, they will equal the last value of i.
Some breaking changes were in new compiler versions. The new version of the code:
1
public void Run()
2
{
3
var actions = new List<Action>();
4
foreach (int i in Enumerable.Range(1, 3))
5
{
6
DisplayClass c1 = new DisplayClass();
7
с1.i = i;
8
list.Add(c1.Action);
9
}
10
foreach (Action action in list)
11
action();
12
}
13
14
private sealed class DisplayClass
15
{
16
public int i;
17
18
public void Action()
19
{
20
Console.WriteLine(i);
21
}
22
}
Copied!
Now, each element of the list refers to own delegate, all printed values will be different.
Examples:
1
Mono compiler 2.4.4 : 3 3 3
2
Mono compiler 3.10.0 : 1 2 3
3
Mono compiler 3.10.0 langversion=4 : 1 2 3
4
MS compiler 3.5.30729.7903 : 3 3 3
5
MS compiler 4.0.30319.1 : 3 3 3
6
MS compiler 4.0.30319.33440 : 1 2 3
7
MS compiler 4.0.30319.33440 langversion=4 : 1 2 3
Copied!

Links

Problem
Copy link