Question

I have the following class.

public class myType
{
  public event Action myAction;
}

And a Dictionary containing some instances of that class.

var myDictionary = new Dictionary<myType, string>();

In my Main I have a method with signature void SomeMethod(myType, Dictionary)

With the following loop I add my object's behaviour:

foreach(var pair in myDictionary)
  pair.Key.myAction += () => SomeMethod(pair.Key, myDictionary);

After running this loop, when the action of one of my objects is invoked, the effect is as if the loop had used the last pair.Key in the dictionary for all the lambda expressions.

On the other hand with a small change in the loop:

foreach(var pair in myDictionary)
{
  myType temp = pair.Key;
  pair.Key.myAction += () => SomeMethod(temp, myDictionary);
}

After running this loop, all the object actions work as expected.

I'm a bit at a loss why such a change would have such an effect. A keyvaluepair may be a struct, by the key itself is a reference type (an instance of my class). Any ideas why this behaves this way?

Thanks in advance for any suggestions.

Was it helpful?

Solution

After running this loop, when the action of one of my objects is invoked, the effect is as if the loop had used the last pair.Key in the dictionary for all the lambda expressions.

Yes, that's exactly what's happening. You have a single variable pair that is used by all the event handlers. After the loop the variable contains the key of the last item in the loop.

By creating a local variable in the scope and using that in the lambda expression, you are actually creating a closure for each event handler. The local variable is not stored on the stack as a regular local varible, but in the closure, and as each event handler has its own closure, you get one version of the local variable for each event handler.

(There is a closure with the first code also, but that is just for the variable to survive the current scope, the event handlers share the same closure.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top