Remove handler when usercontrol is disposing

2019-07-28 06:45发布

Which one is the right one?

This one:

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
        components.Dispose();
    }
    base.Dispose(disposing);
}

OR

This one:

~ ctlRemoteBuildContent1()
{
    this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
}

I tried to toggle this 2 functions. When I did UserControl disposing, it didn't jump into the toggle line :/

3条回答
叼着烟拽天下
2楼-- · 2019-07-28 07:14

The second bit of code is called by the finalizer, which means you won't be able to tell when this is called (depends on when the garbage collector runs). Ideally you want to free your resources as soon as possible, typically in a Dispose(). So use the dispose pattern here.

Why do you want to unsubscribe that event here? What does it contain?

查看更多
祖国的老花朵
3楼-- · 2019-07-28 07:24

If you clean up in a destructor, there's no guarantee as to when the destructor will be run. Objects with a destructor also require more work for the garbage collector to handle. It's preferable therefore to implement IDisposable, which is your first example.

Note that your code snippet does not fully implement the recommended IDisposable pattern. Please see this article for a good and complete explanation:

http://www.csharphelp.com/2010/02/c-garbage-collecting-destructors-versus-dispose/

In your code snippet, if for some reason components is null, you would not remove the event handler. The null check for components should only be done to protect the components.Dispose() call.

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this.ctlRBContent1_GetBuildName -= _ctlBottom.GetBuildName;
        if (components != null)
        {
            components.Dispose();
        }
    }
    base.Dispose(disposing);
}
查看更多
何必那么认真
4楼-- · 2019-07-28 07:26

Which one is the right one?

A slightly obnoxious answer is "both" ;-) ...

Ideally you want the tidying up to happen in the Dispose method so it can be performed as soon as possible, but in some situations it's important to also have the tidy up code called from the destructor as a back-up in case an object gets used without being disposed (...I guess it depends on how likely you think this could be!?)

The dispose pattern (mentioned in the other answers) provides a way of implementing this without code duplication between the dispose and destructor, and with the GC.SupressFinalize makes sure the object's garbage collection doesn't get held up unnecessarily if the tidy up has been done.

查看更多
登录 后发表回答