Marty
Marty

Reputation: 7522

Why does the WinForms designer generate somewhat 'inconvenient' code in its dispose method?

When you create a form or a user control, the WinForms designer generates a dispose method that looks like this:

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

The problem with this code is that it can lead to incorrect behaviour if it is ever edited to dispose of additional objects. I have seen .designer.cs files with dispose methods that look like this:

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
            if (_myDisposable != null)
                _myDisposable.Dispose();
            if (_myOtherDisposable != null)
                _myOtherDisposable.Dispose();
        }
        base.Dispose(disposing);
    }

... which is incorrect, as the disposal of _myDisposable and _myOtherDisposable should not depend on whether or not components is null.

So, ignoring the argument about whether or not it is good practice to edit this designer generated code, and ignoring the fact that you can change it by editing the templates, my question is: Why doesn't the designer generate code that looks more like this?

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if(components != null)
                components.Dispose();
        }
        base.Dispose(disposing);
    }

This code has the same end result, but is safer and less prone to errors during modification.

Upvotes: 5

Views: 1085

Answers (4)

Roman Starkov
Roman Starkov

Reputation: 61512

I would argue that this is because the Microsoft's "official" IDisposable pattern tries to accomodate too many situations, unnecessarily.

For more details, see this excellent article by Stephen Cleary: [What your mother never told you about IDisposable]https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About). He has some great insights into the issues with IDisposable, and how to fix them.

Stephen offers one simple guideline: just don't mix managed and unmanaged resources in a single class; instead, wrap every unmanaged resource in an IDisposable class whose sole purpose is to dispose of the unmanaged resource.

If one follows this guideline, such arcane Dispose methods stop being necessary, at the same time as solving a whole bunch of other, more serious issues with Microsoft's recommended pattern.

Upvotes: 3

Henk Holterman
Henk Holterman

Reputation: 273691

You're right mostly, and you didn't even mention the fact that it is placed inside the Designer.cs file.

You'll have to first move it (to MyForm.cs) and then edit it. With some common sense...

But it is largely academic, components==null will only be true on a completely empty Form. Drop 1 Button or Label and the issue doesn't come up.

I just checked, even on an empty Form it is not null. (OK, just for Fx 4+ apparently)

Upvotes: 1

Dan Bryant
Dan Bryant

Reputation: 27515

The recommended way to handle Disposal of contained resources on a Form is to use the FormClosing or FormClosed events. UserControl has a Disposed event for the same purpose.

Upvotes: 1

Mike Nakis
Mike Nakis

Reputation: 62130

The answer is: because your convenience was not the primary concern of whoever wrote this function at Microsoft. Or perhaps they thought that you, being a non-Microsoft employee, cannot possibly be any good as a programmer, therefore, you should probably stay away from risky businesses such as modifying an object's Dispose() method.

By the way, the Dispose() method lies outside of the area within the .Designer.cs file which is designated as "do not edit this designer generated code", so I suppose it is okay to edit it.

Upvotes: 5

Related Questions