Actually you do not need to call Dispose()
on web form controls that you add to a parent page. I, too, saw these warnings and was trying to figure out how to handle them and before wrapping all of the control creations in using
statements I tested whether or not dispose is actually called on a control that was added to a parent.
TestDispose.ascx.cs:
public partial class TestDispose : System.Web.UI.UserControl {
public void override Dispose() {
// Set breakpoint here
base.Dispose();
}
}
TestPage.aspx.cs:
public partial class TestPage : System.Web.UI.Page {
public void override OnInit() {
// test will be disposed of when the page is destroyed
TestDispose test = new TestDispose();
test.ID = "TestDispose";
this.Controls.Add(test);
// test1 will not be disposed of because it was not added
// to the page's control tree.
TestDispose test1 = new TestDispose();
test1.ID = "TestDispose1";
}
}
If you run this in the debugger with a breakpoint on TestDispose.Dispose()
you'll find out that Dispose()
is called by the parent page as the page is being destroyed. Once I determined this I started adding exclusions with the justification of 'Dispose()
is called on objects within the Page's Control tree.'
Update
The one thing that bothers me is I cannot find this actually documented anywhere. While the ASP.Net Page Lifecycle is a good resource it doesn't mention calling Dispose()
on child controls.
Using Reflector, however, I was able to determine that Dispose()
is called through the following hierarchy:
System.Web.UI.Page.AspCompatBeginProcessRequest
-> System.Web.UI.Page.ProcessRequest
-> System.Web.UI.Page.ProcessRequestCleanup
-> System.Web.UI.Control.UnloadRecursive
System.Web.UI.Control.UnloadRecursive
will loop through each Controls property and end up calling Dispose()
for each Control object. Any object which inherits from System.Web.UI.UserControl
implements IDisposable
.
So, unfortunately, without actual documentation we are currently relying on an implementation detail and not a contract. While I won't change my exclusions/justifications because of this, I just wanted to bring this to light for other readers of this answer.