You would think that I would learn: Anonymous delegate variable capturing gotcha
Can you think of anything wrong with this code:
foreach (DataSource value in EtlConfigurationContext.Current.Sources.Values) { ExecutionPackage.Current.RegisterForExecution( delegate { value.Start(this); } ); }
I stared that this thing for a while before it hit me. Anonymous delegates lexical capture rules inside a loop means that it will take the loop variable, which has the gotcha of keeping the last value of the variable. This keep tripping me, and I really wish the spec would have made an exception for a loop, because this really is a gotcha and not something that I really need to be concerned with.
In keeping with "code should be self documenting" the bug fix looks like this:
foreach (DataSource value in EtlConfigurationContext.Current.Sources.Values) { DataSource cSharpSpec_21_5_2_Damn_It = value; ExecutionPackage.Current.RegisterForExecution( delegate { cSharpSpec_21_5_2_Damn_It.Start(this); } ); }
Comments
LOL.
That really is self-documenting.
Makes me feel better that it happens to other people, too. Took me FOREVER to figure out what was going wrong ... I made a post about it when I discovered it to remind myself (http://bananas.piasecki.name/index.php?go=home&tags=2:81&snippet=39).
Nicholas,
All I see at your site are bananas :-)
I wouldn't have mind tripping over it once, but this is not the first time by a long shot.
I don't mind "for" declaring a single variable, but I would like "foreach" to instantiate a new local variable on each iteration. If you look at a for loop it looks like there's only one local variable instance:
for (int i=0; i < 10; i++)
The declaration part there is in the section which is only executed once. However, looking at foreach there isn't much distinction:
foreach (string value in someCollection)
Given that "value" is readonly within the foreach loop, it feels like there's an implicit new variable for each iteration. The fact that there isn't is what causes the problem here.
And yes, I've been hit by exactly the same issue, despite knowing about it beforehand. Grr.
I actually ran into this last week myself!
I cursed something and muttered under my bread and implemented the exact same workaround :)
Comment preview