Is disposing a panel equivalent to disposing its c

2019-05-23 11:47发布

问题:

Within the following class:

class MyPanel : Panel
{
    ...
    protected override void Dispose(bool disposing)
    {
        // My code here
    }
}

are the following two code samples equivalent?

base.Dispose(disposing);

vs

if (disposing)
{
    List<Control> ctrls = new List<Control>(this.Controls);
    this.Controls.Clear();  
    foreach(Control c in ctrls)
    {
         c.Dispose();
    }
}
base.Dispose(disposing);

If they have a different effect, what would it be?

Edit: I ask this because, for whatever reason, doing it the first way freezes my program before it gets to disposing any of its children (disposing is true, and Controls contains 2 controls), whereas the second way works fine. If I can happily use the second one, then that's great.

回答1:

Yes, disposing the container will automatically dispose of its child controls.

According to the MSDN documentation, the Control.Dispose method:

Releases the unmanaged resources used by the Control and its child controls and optionally releases the managed resources.

So calling the Dispose method on the Panel control will automatically dispose its child controls. However, there is an important caveat to this, as noted by Joe's comment: the child controls must have unsubscribed from events that are declared outside of the parent's scope. If the events are members of objects that will stay alive, they will keep the child controls alive as well and prevent them from being properly disposed. Obviously you don't need to unsubscribe from events declared in objects that are being disposed of simultaneously, such as the parent.

Of course, it's also worth nothing that this can be extended to the Panel control's container (most likely a Form control). Whenever you Dispose the Form that owns the Panel, both the Panel control and all of its children will be disposed for you automatically. There's no reason to do so explicitly for the Panel control, unless you're adding and removing instances to and from your form dynamically.



回答2:

The two are not identical, as you can easily see by looking at the implementation of Control.Dispose using Reflector (easy to do while it's still free!)

For example, if you just call Dispose on your panel, it will call DisposeAxControls on each child control, and remove itself from its parent, before calling Dispose on its children.

Nevertheless I agree with Cody Gray - you need to work out why it's freezing rather than trying to "sweep the problem under the carpet" with your proposed workaround.

Normally you don't call Dispose on a Panel explicitly - if you are doing so, you need to be sure you're managing the lifetime and ownership of your controls correctly.

The thing to do is to start simplifying your app step by step until it no longer freezes - to work out what is causing the freeze (for example, by removing the Timers you mentioned one by one - that sounds suspect). Once you have a very simple example that exhibits the problem it will be easier for you (or someone here) to work out what's going on.