Z
Zachary Turner
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/thread/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
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/thread/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