Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm General / May 2006

Tip: Looking for answers? Try searching our database.

When to call Dispose

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Zachary  Turner - 22 May 2006 21:31 GMT
Hello,

The question I have below was originally posted to
microsoft.public.dotnet.framework, as I mistakenly considered this a
question of more general nature.  However, the discussion there quickly
turned into one that was very windows forms specific, and it seems
there is some confusion as to the exact answer to my question there
anyway.  For those interested, you can see the initial thread here:

http://groups.google.com/group/microsoft.public.dotnet.framework/browse_frm/thre
ad/376ad6d24e835788


The long and short of is that I don't know -when- to call Dispose() on
various types of Windows Forms objects.  Do you call it -immediately-
after manually removing a control from a collection, or do you call
after you've removed a control from a collection -for the last time-?
The distinction is important, for example in situations where you may
have a single control that is added and removed multiple times
throughout the life of the application.  Of course, you can be
guaranteed correctness by calling Dispose() every time you remove a
control from a collection, and if you need to add it back you create
another identical control with the new() operator.  But this is
inefficient, and doges the real question at hand.

I wrote a little test app.  It's a single form with two buttons and one
list view.  The list view is initialized through the designer to
contain a single column header.  The click handlers for the two buttons
are displayed below.

private bool bRemoved = false;
private bool bRemoved2 = false;

private void button1_Click(object sender, EventArgs e)
{
    if (!bRemoved)
    {
        this.Controls.Remove(listView1);
        listView1.Dispose();
    }
    else
        this.Controls.Add(listView1);
    bRemoved = !bRemoved;
}

private void button2_Click(object sender, EventArgs e)
{
    if (!bRemoved2)
    {
        listView1.Columns.Remove(columnHeader1);
        columnHeader1.Dispose();
    }
    else
        listView1.Columns.Add(columnHeader1);
    bRemoved2 = !bRemoved2;
}

The idea behind this test was to just see what would happen.  Will it
even work, or will it throw an exception somewhere?  (what's happening,
of course, is that the items are getting disposed multiple times and
added back to the respective collections even after being disposed.)

In the case of the list view, this actually seems to work.  The column
header appears and reappears in the list view on successive clicks of
the button.  The listView itself, however, does not.  Clicking button1
the first time removes the listView, and clicking it a second time does
NOT put the listView back on my form.  Still no exception on subsequent
calls to Dispose() though.

- Should these types of objects be treated semantically different?  If
so, how do other objects work regarding Dispose()?
- Am I just getting lucky with the columnHeader case, but it may
exhibit other types of problems down the line?

I think the MSDN documentation leaves a bit to be desired here, because
all it says is something along the lines of "You need to call Dispose()
manually on these objects if they are not in the container when the
container itself is Disposed().  It doesn't answer the question of when
to Dispose() them though, and if they are reusable
Mehdi - 22 May 2006 23:00 GMT
>  - Should these types of objects be treated semantically different?  If
> so, how do other objects work regarding Dispose()?

No. All object from IDisposable classes should be treated in the same way:

- you should call Dispose whenever you do not need the object anymore. Note
that if the object is a control placed in a container control, the
container control will dipose it when disposed itself.

- if the IDisposable class has been implemented following Microsoft's
recommendations (you can safely assume that all the .NET framework classes
follow these recommendations), it is safe to call Dispose() on an object
that has already been disposed (that is: it is safe to call Dispose()
multiple times and this will not result in an exception to be thrown). In
other words, you can call Dispose() on your controls without having to
worry on whether they were still placed in their container control or had
been removed from it.

- You must never re-use an object that has been disposed. In the case of
Controls, you should not attempt to re-add a disposed control to a
container control or access its methods or properties. What happens when
you try to re-use a disposed object varies depending on how the developer
of the class has implemented it. He might have added explicit checks at
each of the properties and methods of the class to check if the object has
already been disposed and throw ObjectDisposedException is the object
happens to have been diposed. In this case, you won't be able to do
anything with the object anymore after it's been disposed. However, in many
cases, the developer doesn't bother adding these checks. If this is the
case, the object might appear to be still usable after having been disposed
but its behaviour will be unpredictible since it's internal state might now
be corrupted. Note that some class implement IDisposable only because they
derive from a class that implements it but do not actually do anything in
their Dispose method. In this case, re-using the disposed object would work
but since you are not supposed to know how the class has been implemented,
you should not rely on that. I'm not sure of what happens when a Control is
diposed. I suppose that, at the very least, its window handle is destroyed.
If you want to know what happens under the hood, have a look at Reflector.

>  - Am I just getting lucky with the columnHeader case, but it may
> exhibit other types of problems down the line?

You might be lucky for the moment and encounter weird problems later or it
might be that the Dispose method of your columnHeader object does not
actually do anything. You can check that out using Reflector. In either
case, you should not attempt to re-use your columnHeader after having
disposed it as even if its implementation allows that for the moment,
nothing tells you that it's still going to be the case in a future version
of the .NET Framework.
Zachary  Turner - 23 May 2006 02:59 GMT
Thanks for the excellent answer.  On that note, is it safe to assume
that it is perfectly valid and correct (despite the questionable
usefulness) to have the following code?

void f()
{
 listView1.Columns.Add(Header1);
 listView1.Columns.Remove(Header1);
 listView1.Columns.Add(Header1);
}
Mehdi - 23 May 2006 08:42 GMT
> Thanks for the excellent answer.  On that note, is it safe to assume
> that it is perfectly valid and correct (despite the questionable
[quoted text clipped - 6 lines]
>   listView1.Columns.Add(Header1);
> }

Yes, it is perfectly valid.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.