Anonymous Methods scope question

G

Gabe Moothart

Hello,
In one of my asp.net applications, I create a series of checkboxes, set
their properties, and give them an "onChecked" event handler on the fly
using an anonymous method. The code looks like this:

protected void Page_Load(object sender, EventArgs e)
{
Dictionary<Guid, string> dataHash = ... //db access
foreach(KeyValuePair<Guid, string> row in dataHash)
{
CheckBox cb = new CheckBox();
cb.ID = row.Key.ToString();
cb.Text = row.Value;
cb.AutoPostBack = true;

//mark the checkbox checked/unchecked
cb.Checked = ...

cb.CheckedChanged += delegate( object sender, EventArgs e )
{
if (cb.Checked) {
... //save state
}
else {
... //save state
}
};

//add this checkbox to the page
PlaceHolder1.Controls.Add( cb );
PlaceHolder1.Controls.Add( new HtmlGenericControl( "br" ) );
} //foreach
} //PageLoad

I've coded this up, and it seems to work. But upon further reflection,
I'm not sure why. Notice that I reference the local variable cb inside
the anonymous event handler. I know that anonymous methods have access
to their enclosing scope, which is why I can do that. But the scope that
they have access to is updated by every loop iteration, isn't it? And
shouldn't that change the object that cb points to?

Essentially I think that, when these anonymous event handlers are
invoked, their copy of cb should always be a reference to the _last_
CheckBox created - because they have a reference, not a copy, of their
containing scope.

So, my questions are:
1) Why does this work?
2) Is this a safe pattern for adding event handlers? Is it likely to
bite me in the future?

Thanks,
Gabe
 
J

Jon Skeet [C# MVP]

Gabe Moothart said:
Essentially I think that, when these anonymous event handlers are
invoked, their copy of cb should always be a reference to the _last_
CheckBox created - because they have a reference, not a copy, of their
containing scope.

No - local variables have gained the concept of an "instance".
Basically, each time you go round the loop, you're redeclaring cb and
creating a new "instance" of the variable. It's that "instance" that is
captured by the anonymous method.

It gets more confusing when you access some variables from an inner
scope and some variables from an outer scope. Note that the variable
declared in a "foreach" loop only has a single instance for the whole
loop.
So, my questions are:
1) Why does this work?
2) Is this a safe pattern for adding event handlers? Is it likely to
bite me in the future?

Shouldn't do in this case - but you need to be clear as to what's going
on.
 
G

Guest

Essentially I think that, when these anonymous event handlers are
Invoked, their copy of cb should always be a reference to the _last_
CheckBox created - because they have a reference, not a copy, of their
containing scope.

[This is true if you declare CheckBox cb = null; before the foreach block]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top