Reputation: 90495
The following program
static IEnumerable<Action> Create()
{
foreach (var i in Enumerable.Range(0, 2))
{
yield return () => { Console.Write(i); };
}
}
static void Main(string[] args)
{
foreach (var func in Create())
{
func();
}
Console.ReadLine();
}
ouputs
01
And this program
static event Action SomethingHappened;
static void Register()
{
foreach (var i in Enumerable.Range(0, 2))
{
SomethingHappened += () => { Console.Write(i); };
}
}
static void Main(string[] args)
{
Register();
SomethingHappened();
Console.ReadLine();
}
outputs
11
Why is that so? How to make the program 2 output 01
?
Upvotes: 0
Views: 55
Reputation: 116411
In the second program the variable i
is captured by the lambda. To get the correct behavior make a local copy before using it in the lambda. E.g.
foreach (var i in Enumerable.Range(0, 2))
{
var local = i;
SomethingHappened += () => { Console.Write(local); };
}
Upvotes: 1
Reputation: 1501143
You're capturing the loop variable in your lambda expression. That means when the delegate is finally invoked, it will use the latest value of the variable... which will always be 1. Try this:
foreach (var i in Enumerable.Range(0, 2))
{
int copy = i;
SomethingHappened += () => { Console.Write(copy); };
}
... then read Eric Lippert's blog post about it.
Upvotes: 3