Retrieving lambda expressions from a collection

I am very new to lambda expressions in C # and I am having problems conceptualizing how they are stored / retrieved in a collection.

I am trying to programmatically create a list of 10 Funcs x => x + 1, x => x + 2 , etc. as a test. My desired result is 0,1,2,3,4,5,6,7,8,9

Here is my code for this:

var list = new List<Func<int, int>>(); for (int i = 0; i < 10; i++) { Func<int, int> func = x => x + i; Console.WriteLine("a) " + func.Invoke(0)); //returns 0,1,2,3,4,5,6,7,8,9 list.Add(func); Console.WriteLine("b) " + list[i].Invoke(0)); //returns 0,1,2,3,4,5,6,7,8,9 } foreach (var func in list) //returns 10,10,10,10,10,10,10,10,10,10 Console.WriteLine("c) " + func.Invoke(0)); for(int i = 0; i < list.Count; i++) //returns 10,10,10,10,10,10,10,10,10,10 Console.WriteLine("d) " + list[i].Invoke(0)); 

I get the same results when replacing the Func array for the [Func] list .

What am I missing?

+4
source share
3 answers

Make me local in lambda by copying it to a new variable:

 var list = new List<Func<int, int>>(); for (int i = 0; i < 10; i++) { var temp = i; Func<int, int> func = x => x + temp; Console.WriteLine("a) " + func.Invoke(0)); //returns 0,1,2,3,4,5,6,7,8,9 list.Add(func); Console.WriteLine("b) " + list[i].Invoke(0)); //returns 0,1,2,3,4,5,6,7,8,9 } foreach (var func in list) //returns 0,1,2,3,4,5,6,7,8,9 Console.WriteLine("c) " + func.Invoke(0)); for (int i = 0; i < list.Count; i++) //returns 0,1,2,3,4,5,6,7,8,9 Console.WriteLine("d) " + list[i].Invoke(0)); 
+7
source

Your problem is that the lambda expression captures the variable that you used to define it.

Since the entire loop, the generated list has the same variable, all delegates will return 10.

To solve this problem, declare a separate variable inside the generation loop, assign it to i , and then use it in the lambda expression.

For instance:

 var list = new List<Func<int, int>>(); for (int dontUse = 0; dontUse < 10; dontUse++) { var i = dontUse; Func<int, int> func = x => x + i; list.Add(func); } foreach (var func in list) Console.WriteLine("c) " + func(0)); 

See this blog post for more information.

By the way, when calling delegates you do not need to write func.Invoke(params) ; you can just write func(params) .

+4
source

All Articles