I have some code,
int count = 0;
list.ForEach(i => i.SomeFunction(count++));
This seems to not increment count. Is count passed by value here? Is there any difference if I use the {} in the lambda?
int count = 0;
list.ForEach(i =>
{
i.SomeFunction(count++);
});
Update 1
Sorry, my mistake, it does update the original count.
In this case, the
count
variable is captured. Even if it's astruct
the captured variable acts like its a reference. So, you would certainly see an incrementedcount
after theforeach
.In both cases you are creating what's called a closure. Essentially, count is being wrapped in a class and that class is being used by the lambda expression.
Bill Wagner has a great book called More Effective C# and he has a blog post that describes closures in more detail.
That should increment, proof:
The lambda acts (as already stated) to "capture" count, essentially making the code like:
The above is a rough approximation of how the compiler interprets a delegate lambda. As you can see, the
count
is a field on a class, and is incremented.Lambdas are anonymous functions, and as such, follow the same rules as passing arguments into a function.
count
is an int, and ints are value types, which means they are indeed passed by value. There is no semantic difference between your first and second example.(That said, it looks to me like it should be incrementing
count
, since it should be capturing the original reference as far as the closure. To clarify -- although count will be passed by value down into SomeFunction, things don't get "passed" into your lambda expression when you use them inside the expression -- they are the same reference as the external variable.)That should capture (close over) count as a closure.