to dispose or not ?

  • Thread starter Michel Posseth [MCP]
  • Start date
C

Cor Ligthert[MVP]

Brian,

Because you and some others here wrote that unrestricted "every" class that
holds a dispose method is a warning that it "must" call the dispose method

I did not write that, I've written what you now wrote here more times, now
you come with reflector and not with an sample,

Cor



Michel,

In my idea have I asked you earlier to show us a sample where you use the
using on the controls on a form.

They all implements Idisposable.

Labels, Comboboxes, textboxes, tooltips, I've showed you that list in a
previous message.

I really am awaiting expecting full to see that done with using?

In my idea it will looks like a mesh, but I am always glad to be
surprised.

Cor

Why would we want to use 'using' on Windows Forms controls? First,
they're almost always class members which makes it impossible to use
'using' in semantically correct way. Second, the Dispose method is
already called automatically by the various control containers. And I
might add that the Form class does implement the IDisposable correctly
here. That is, it's own Dispose method recursively calls Dispose on
it's constituent IDisposable members. So unless you have some one-off
case where the lifetime of the control is not tied to the lifetime of
the containing Form then there's no reason to inject a second
superfulous call to Dispose.

You said you wanted an example. Use Reflector to see what
Form.Dispose is doing. You should be able to convince yourself that
the Dispose method really is called on the Windows Forms controls.
 
C

Cor Ligthert[MVP]

Tom,

That is only when you use a template or write it yourself.
By the way, not only the form contains that piece of code, it is in more
templates and AFAIK in fact is that overriding of dispose the correct
implementation of Idisposable.

About dialogforms, Although I am mostly using the using, is that not for a
dialogform.
Here I use the dispose method, simply because here it is less code and in my
idea easier to read.

Cor
 
T

Tom Shelton

Well, it would help with extensive methods wherein you were done using an
instance well before the method completes and that's where I would set
things to Nothing.

-Scott

I believe that's the optimize memory usage thing I was talking about :)
 
T

Tom Shelton

But, would this not help in older versions of the Fraework? I still have
clients using 1.x!

AFIK, this has been the behavior since the first release. It was some of the
beta's I believe that didn't do optimizations that had this behavior.
 
B

Brian Gideon

Brian,

Because you and some others here wrote that unrestricted "every" class that
holds a dispose method is a warning that it "must" call the dispose method

To be precise I'm saying that Dispose *should* be called on every
class.
I did not write that, I've written what you now wrote here more times, now
you come with reflector and not with an sample,

I think I see what you're saying. I told you (or at least inferred)
that peeking into the implementation is not sufficient to justify a
decision regarding whether Dispose should be called. You're using the
same logic to point out that I'm making the same fallacy by
recommending that you look inside Form.Dispose.

Here's the difference. In the first case you are circumventing the
concepts of encapsulation to *make a programming decision*. And in
the second case you're not.

My recommendation to look inside the Form.Dispose method was not to
justify a programming decision, but to convince you that the BCL code
really is complying with the rules of the IDisposable interface as I
claimed it did. That is the Form.Dispose method really is calling
Dispose on all constituent IDisposable members and thus all controls
are necessarily disposed of already. It's not that you *have* to do
this. I just thought seeing concrete proof as opposed to a sample
would be more meaningful.
 
H

Herfried K. Wagner [MVP]

Brian Gideon said:
http://blogs.msdn.com/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx

Basically, only one of the prominent figures was in the "avoid calling
dispose" camp. But, personally, I find his arguments weak.

First, he gives the example of the IAsyncResult class returned by
FileStream.BeginRead. It contains a WaitHandle member that implements
IDisposable. An unsuspecting caller may extract the instance from
this member with the sole purpose of calling Dispose without realizing
that the property actually lazily initializes the wait handle to begin
with. The problem here is that IAsyncResult is poorly designed in
that regard and doe not adhere to Microsoft's own published guideline
that states if a class or interface holds (either directly or
indirectly) that it too must implement IDisposable in which case that
implementation could decide which of it's members actually needed to
be disposed.

I would not call 'Dispose' on objects which I didn't create explicitly in
the code (exception: objects returned by factory methods).
 
H

Herfried K. Wagner [MVP]

Stewart Berman said:
The difference between:
Dim a as Object = New object()
and
Dim a as Object
<code>
a = New object()

Is in performance. In the first case the compiler has to add a test to
see if the object exists
before every reference to it so it can be "automatically" created if it
doesn't exist. In the
second case there isn't any additional code needed. At least that is the
way it worked in VB6. I
haven't looked at this in VB.NET. In the first case, if the object is
never referenced it is never
created.

That's not the case in VB.NET any more. I assume that you are referring to
'Dim x As New Y' vs. 'Dim x As Y : x = New Y'. 'Dim x As New Y' led to the
auto-instantiation behavior which would assign a new instance to 'x' when
attempting to access the variable after it has been set to 'Nothing'.
 
H

Herfried K. Wagner [MVP]

Scott M. said:
Why do you set the object to Nothing? This doesn't buy you anything and,
in fact, can actually delay cleanup of your object, rather than hasten it.

I would avoid the terminology "setting an object to 'Nothing'" as it is
misleading (except for value types). Actually a /reference/ is set to
'Nothing' and the object it has been pointing to doesn't necessarily get
destroyed (depending on the GC strategy).
 
S

Scott M.

I could be wrong but I had thought that, at least the 1.x Frameowrk (final
releases) were not optimized to take care of this. I have several books
that refer to the problem.
 
B

Brian Gideon

I would not call 'Dispose' on objects which I didn't create explicitly in
the code (exception: objects returned by factory methods).

That's a really good point.
 
B

Brian Gideon

I think I see what you're saying.  I told you (or at least inferred)
that peeking into the implementation is not sufficient to justify a
decision regarding whether Dispose should be called.  You're using the
same logic to point out that I'm making the same fallacy by
recommending that you look inside Form.Dispose.

Here's the difference.  In the first case you are circumventing the
concepts of encapsulation to *make a programming decision*.  And in
the second case you're not.

My recommendation to look inside the Form.Dispose method was not to
justify a programming decision, but to convince you that the BCL code
really is complying with the rules of the IDisposable interface as I
claimed it did.  That is the Form.Dispose method really is calling
Dispose on all constituent IDisposable members and thus all controls
are necessarily disposed of already.  It's not that you *have* to do
this.  I just thought seeing concrete proof as opposed to a sample
would be more meaningful.

By the way concept we're now discussing is one of ownership. If you
didn't explicitly created the IDisposable then you're probably not on
the hook to Dispose it either. However, the real owner still is. And
in that regard Dispose is still getting called. It's just a matter of
who is doing it.
 
S

Scott M.

It's just a matter of who is doing it.

....And, as such, when Dispose takes place...In the developer's code at a
planned point or by (maybe) the GC at some later point.
 
S

Scott M.

FYI:

From: "Professional Visual Basic 2008" by Bill Evjen, Billy Hollis, Bill
Sheldon, & Kent Sharkey:

Chapter 4 (The Common Language), Page 206:

...."Perhaps more important is the fact that the GC will at times reclaim
objects in the middle of executing the code in a method. Fortunately, the
system ensures the collection only happens as long as your code doesn't
reference the object later in the method.

For example, you could actually end up extending the amount of time an
object is kept in memory just by setting that object to Nothing. Thus,
setting a variable to Nothing at the end of the method prevents the garbage
collection mechanism from proactively reclaiming objects, and therefore is
generally discouraged."

I've read this over and over from the beginning of .NET up to and including
the current Framework version. I've not seen anything indicating that the
compiler can check for Nothing assignments and optimize them away so that
this problem is avoided.

Can you provide some documentation for me to look at to verify this
behavior?

-Scott
 
S

Scott M.

It seems that my original assertion that setting an object reference to
Nothing will, in fact, potentially delay the object's removal from the heap
if the GC collects during a method where the object was instantiated, but
not used anymore, at the point that the GC collects, is correct.

TheGC has a KeepAlive method MSDN explains:
"The purpose of the KeepAlive method is to ensure the existence of a
reference to an object that is at risk of being prematurely reclaimed by the
garbage collector. A common scenario where this might happen is when there
are no references to the object in managed code or data, but the object is
still in use in unmanaged code such as Win32 APIs, unmanaged DLLs, or
methods using COM.

This method references the obj parameter, making that object ineligible for
garbage collection from the start of the routine to the point, in execution
order, where this method is called. Code this method at the end, not the
beginning, of the range of instructions where obj must be available.

The KeepAlive method performs no operation and produces no side effects
other than extending the lifetime of the object passed in as a parameter."

ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/2e1bb318-c0dc-11f7-875f-6d25db308dab.htm

-Scott
 
B

Brian Gideon

FYI:

From: "Professional Visual Basic 2008" by Bill Evjen, Billy Hollis, Bill
Sheldon, & Kent Sharkey:

Chapter 4 (The Common Language), Page 206:

..."Perhaps more important is the fact that the GC will at times reclaim
objects in the middle of executing the code in a method.  Fortunately, the
system ensures the collection only happens as long as your code doesn't
reference the object later in the method.

For example, you could actually end up extending the amount of time an
object is kept in memory just by setting that object to Nothing. Thus,
setting a variable to Nothing at the end of the method prevents the garbage
collection mechanism from proactively reclaiming objects, and therefore is
generally discouraged."

I've read this over and over from the beginning of .NET up to and including
the current Framework version.  I've not seen anything indicating that the
compiler can check for Nothing assignments and optimize them away so that
this problem is avoided.

Can you provide some documentation for me to look at to verify this
behavior?

I agree with the general point described by the author. However,
setting a reference is not the same as using a reference. There's no
reason (that I can think of anyway) why the GC couldn't proactively
collect an object even if one of its reference variables is set to
Nothing later on regardless of whether the compiler can optimize out
that assignment statement.
 
S

Scott M.

I agree with the general point described by the author. However,
setting a reference is not the same as using a reference. There's no
reason (that I can think of anyway) why the GC couldn't proactively
collect an object even if one of its reference variables is set to
Nothing later on regardless of whether the compiler can optimize out
that assignment statement.

By "setting" the object variable, you are instructing the compiler to locate
the memory address that the variable points to, which, in turn, means that
you intend to work with whatever is in that memory address, thereby making
the object in that address continue to have an "application root" reference,
whcih disqualifies the object from being elligible for collection.

While I don't disagree that the GC "could" be written to ignore object
references that have the reference being set to "Nothing", my point is that
I don't believe this is actually the way it is currently written. I see
ample documentation indicating that it is not optimized in this way.

Also, the KeepAlive method of the GC seems to exist because of this behavior
(see my other post).

-Scott
 
S

Stewart Berman

Wouldn't setting the object to nothing serve the same purpose as calling the KeepAlive method? It
is a marker for the last place in code that the object is needed. Furthermore, if, by some chance,
the code is too complicated for the GC to figure out that the object is no longer needed at that
point, setting the reference to nothing reduces the reference count to zero and lets the GC know
that the object can be collected early.

Isn't:
obj = nothing
Clearer than:
GC.KeepAlive(obj)
To indicate that obj is no longer needed?

I am also somewhat confused by the example. It does not appear that the console control handler is
removed anywhere in the code. So if it is collected after the GC.KeepAlive(hr) call wouldn't the
Console.Read() cause a problem if the user responded with Ctrl-C?
 
S

Scott M.

Effectively, yes, the KeepAlive method accomplishes the same thing as
setting the object to Nothing. However, for clarity, MS provides this as a
way to explicitly state in your code that you want and need the object to
stay alive until a certain point, whereas setting it to Nothing could be
misconstrued as being arbitrarially placed in the code as some sort of
default "I'm done now." point. In effect,

GC.KeepAlive(obj) is clearer than obj = Nothing

I think this method was explicitly added to differentiate how VB 6
developers used Nothing vs. how GC works in .NET.

As for the code being too complicated for the GC to figure out if the object
is still being used, you really can't write any code to complicated for the
GC to figure that out, so that's a non-issue.

For the example MS gives, I don't see how CTR-C would affect things any
differently than any other form of input. Console.Readline doesn't care
what you type, it's the carriage return (ENTER) that causes the method to
return. Did I miss something in your question?

-Scott


Stewart Berman said:
Wouldn't setting the object to nothing serve the same purpose as calling
the KeepAlive method? It
is a marker for the last place in code that the object is needed.
Furthermore, if, by some chance,
the code is too complicated for the GC to figure out that the object is no
longer needed at that
point, setting the reference to nothing reduces the reference count to
zero and lets the GC know
that the object can be collected early.

Isn't:
obj = nothing
Clearer than:
GC.KeepAlive(obj)
To indicate that obj is no longer needed?

I am also somewhat confused by the example. It does not appear that the
console control handler is
removed anywhere in the code. So if it is collected after the
GC.KeepAlive(hr) call wouldn't the
Console.Read() cause a problem if the user responded with Ctrl-C?
 
S

Scott M.

Found this, does it help?

http://support.microsoft.com/kb/821779

-Scott

Stewart Berman said:
Wouldn't setting the object to nothing serve the same purpose as calling
the KeepAlive method? It
is a marker for the last place in code that the object is needed.
Furthermore, if, by some chance,
the code is too complicated for the GC to figure out that the object is no
longer needed at that
point, setting the reference to nothing reduces the reference count to
zero and lets the GC know
that the object can be collected early.

Isn't:
obj = nothing
Clearer than:
GC.KeepAlive(obj)
To indicate that obj is no longer needed?

I am also somewhat confused by the example. It does not appear that the
console control handler is
removed anywhere in the code. So if it is collected after the
GC.KeepAlive(hr) call wouldn't the
Console.Read() cause a problem if the user responded with Ctrl-C?
 
T

Tom Shelton

It seems that my original assertion that setting an object reference to
Nothing will, in fact, potentially delay the object's removal from the heap
if the GC collects during a method where the object was instantiated, but
not used anymore, at the point that the GC collects, is correct.

No. The whole point of the KeepAlive method is because setting to
null/nothing is not sufficient to keep an object alive. It's to fool the
optimizer in a few rare cases where you don't want this optimization to occur
- such as holding a mutex when you want to run a single instance app, etc.

Here is an article where this behavior is explored:
http://diditwith.net/PermaLink,guid,291f4cfe-e281-41e1-ba53-2727fcb6f30b.aspx

It only occurs when a code is compiled in release mode. Also, this article is
working with VS2005 - but, I'm pretty sure this behavior was around a lot
longer than that....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top