Note the following code:
Control foo = null;
Control bar = null;
int i = 0;
protected void Page_Load(object sender, EventArgs e)
{
test();
test();
Page.Controls.Add(foo);
}
void test()
{
i++;
bar = new Control();
bar.Controls.Add(new LiteralControl(i.ToString()));
if (foo == null)
{
foo = new Control();
foo.Controls.Add(bar);
}
}
When trying out the above code, I was suprised to see the result printed is ‘1’ (not ‘2’).
Im assuming this is because when i’m adding the control bar to foo, foo.Controls.Add() resolves the reference bar, rather than just storing the reference itself.
1) Can anyone confirm this is the case, or possibly elaborate?
2) I have a feeling if I was allowed to do foo.Controls.Add(ref bar); it would show ‘2’, but obviously that syntax is illegal. Is it possible for this to be the case without major refactoring?
Jon Skeet’s answer is good (of course), but I just want to emphasize one point:
Variables of reference type (such as bar and foo) don’t contain objects, they contain references to objects.
So the first time through the test() method, bar contains a reference to a Control which has a 1 in it. And that reference gets added to foo.
The second time through the test() method, bar contains a reference to a different Control, which has a 2 in it. And that reference doesn’t get added to foo.
Why is it a different reference the second time? Because at the start of test() you say
bar = new Control();That stores a reference to a new Control in bar. From there on, bar has nothing to do with the Control it previously referred to, although a reference to that control still lives on in foo’s Controls collection.If you want to change your code so it behaves how you expected, you could do this:
In that case, we only store a new reference in bar one time, so when all is said and done it should still match the reference we added to foo.