to dispose or not ?

  • Thread starter Thread starter Michel Posseth [MCP]
  • Start date Start date
Yes, I call Close if it is available, Dispose if it is available and thenset the object to nothing
before it goes out of scope.  As I see it, the only open item is whether or not to force garbage
collection.

There's no reason to set a reference variable to Nothing before it
goes out of scope. The object referenced by that variable will be
collected in the exact same manner whether or not the variable is set
to Nothing. In fact, what most people don't realize is that objects
referenced by local variables are actually eligible for collection
*before* the variable goes out of scope (assuming of course there are
no other references).

Consider this example.

Public Sub DoSomething()

Dim a As Object = New Object()
Dim b As Object = New Object()

PretendToUseObject(a)

PretendToUseObject(b)

b = Nothing

End Sub

Public Sub PretendToUseObject(ByVal x As Object)
Console.WriteLine("I'm not doing anything with x.")
End Sub

The conventional wisdom is that the objects referenced by 'a' and 'b'
are eligible once DoSomething exits. But, that's not the case. In
reality, the object referenced by 'a' is eligible immediately after
the first call to PretendToUseObject is invoked and even before
PretendToUseObject even completes. The reason is because the GC is
smart enough to know that 'a' is never used after being passed as a
parameter to another method. Now, using that logic we applied to 'a'
you can see that 'b' is eligible before it is assigned to Nothing.
 
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
 
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

Cor - controls are a special exception because the control containers are
responsible for calling dispose. So, simply calling the containers dispose
method is usually enough. Usually, the only time you have to do this is when
dealing with dialog forms:

So, simply doing:

Using myDialog As New MyDialogForm()
If myDialog.ShowDialog () == DialogResult.OK Then
DoCoolStuff()
End If
End Using

Is all it takes.
 
Michel Posseth said:
Hello Scott ,

This thread was started because i have the feeling that some people think
it is a bad thing or even bad coding practice to call dispose
Who, I saw nobody telling that not in this thread or in the previous one.

It was about creating code like this beneath (to take something else than
dispose).

Cstr("MyString").ToString

The code above does nothing wrong, and don't take almost any time.

But it takes time to get the idea why the one who made this did it.
But he did it probably because he was not sure if a string was returned.

:-)

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.
 
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.

Maybe .Net is perfect but I have scars that itch if I don't do my own cleanup. I have had
applications that would not end because an object was still in existence and the garbage collector
ignored it. Of course this was before .Net so maybe it is safe to rely on garbage collection...
 
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 tosee 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.

Maybe .Net is perfect but I have scars that itch if I don't do my own cleanup.  I have had
applications that would not end because an object was still in existence and the garbage collector
ignored it.  Of course this was before .Net so maybe it is safe to relyon garbage collection...

The behavior you describe is not symptomatic of .NET applications.
The two variations you mentioned are equivalent in every respect
except for the obvious differences in the sequence relative to
unrelated intermingled code.

The difference between VB.NET and VB6 lies in the fact that the first
uses a garbage collector and the later a reference counting scheme.

Even in VB6 setting a reference to Nothing when done at the very end
of method had little use. That's because VB6 automatically decrements
the reference count when a reference variable goes out of scope
anyway. However, setting references to Nothing earlier in the method
before other code executes did have practical uses because you could
effectively cause the referenced object to be destroyed well before
the method ended. None of that reasoning, however, even remotely
applies to VB.NET.
 
It was about creating code like this beneath (to take something else than
dispose).

Cstr("MyString").ToString

The code above does nothing wrong, and don't take almost any time.

But it takes time to get the idea why the one who made this did it.
But he did it probably because he was not sure if a string was returned.

:-)

Maybe it's just me...but I'm not seeing how this example could be
equated to the question of whether or not you should necessarily call
Dispose on an object that implements IDisposable. If you're trying to
say that calling Dispose is superfulous, as is the case with calling
CStr on something that is already a string and then calling ToString
on the result as well, then I'll have to disagree there as well.
 
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 doesnt' apply in VB.NET.

Dim a As New Object()
Dim a As Object = New Object()
Dim a As Object
a = New Object()

Are all exactly equal in VB.NET. There is no conecept of autoinstantiation as
in VB6.
Maybe .Net is perfect but I have scars that itch if I don't do my own cleanup. I have had
applications that would not end because an object was still in existence and the garbage collector
ignored it. Of course this was before .Net so maybe it is safe to rely on garbage collection...

VB6 didn't have GC in the same way. It used reference counting to determine
object lifetime. What your describing doens't happen often in .NET (the cases
I've seen are dealing with threads or legacy com objects).
 
Well, that is exactly the point I'm making. You've made an educated
decision about your need to call dispose. As I stated in an earlier post,
if I know for a fact what Dispose does or doesn't do with a type, I'll call
it accordingly. If I don't, I'll call it to be safe and go get educated.

I do belive that Dispose on a DataSet is there to release any hold it may
have on XML files that it uses to read from/write to, but I could be wrong.

-Scott


Again, think about the DataSet, which *may* need to be disposed, depending
on how you use it. If you need to use it, use it. If not, don't. In
reality, Dispose is not unlike any other property or method in that
regard.
Sometimes you *need* to call certain members to do what you *need* and
sometimes you don't.

Actually, I don't think there is a case where Dispose on a DataSet
does anything interesting. I looked at with Reflector, but perhaps I
looked too hastily. Nevertheless, I actually don't call Dispose on a
DataSet which actually contradicts my "always call dispose" position.
But, I omit the call knowing full well the consequences of my decision
if a future version were to have a more useful implementation. It's
just that I find the probability of that exceedingly low as compared
to say...the SqlCommand class.
 
Hi Michael,

I do get your point and can't really make any definitive argument that you
are wrong.

What I think you are hearing here is people's opinions and their coding
styles.

I think that if we've learned anything here (and in every other thread where
this has been debated) is that there is not a concensous in the developer
community on this.

-Scott


Michel Posseth said:
Hello Scott ,

This thread was started because i have the feeling that some people think
it is a bad thing or even bad coding practice to call dispose

We get discussions as "do you call dispose on every forms control" while
in fact this is taken care off by the container ( the documentation even
states that windows forms controls are an exception on the general rule to
calll dispose if availlable ) .

I know that in a lot of objects Dispose isn`t doing annything ( although i
nowadays like the extra scope level hyrarchy it provides when using a
using block ) , so some of you are now saying it is OK not to call
dispose if the method isn`t doing annything , so this means you must check
the current behavior and future behavior of every library you implement
just for the sake of not calling dispose on a object that exposes a
Dispose method .

Some tell that if a object is in method level it isn`t needed at all (
cause the GC would save you ) , although i showed some AD code that really
brings your computer down and the GC looks the other way
while your computer is draining on resources this can be solved by just
making one litle dispose call .

If i whould need to decompile every third part object lib to check if it
actually really needs a call to dispose that would be fun to explain to my
manager.

regards

Michel





Scott M. said:
I don't think anyone is bashing Dispose (at least I'm not). I'm simply
saying that it makes good sense to know something about the classes you
use and, to that end, in certain cases I know I don't need Dispose and in
others I know I do. So I call it when I need to, I don't when it's not
needed, and if I'm not sure, I call it and then go find out more about the
type.

-Scott


Michel Posseth said:
Hello Brian ,


Exact what i mean , it looks to me like the Dispose bashers just take
the risk of there app causing mayhem on the computers resources just
because they are to lazy to call Dispose .

regards

Michel



"Brian Gideon" <[email protected]> schreef in bericht
After a time of abscense reading this newsgroup i read again a lot of
Dispose bashing
I can only say "Again ! " i thought we had discussed this several times

Some facts do not change over time , and if you really think calling
dispose
isn`t necesary at all i invite you to write some AD code you will then
find
that if you do not dispose the smallest object
your program will consume more and more resources untill it hits your
computers limit and blows up with a out of memory exception .

I also read about parrotting blah blah about using Dispose , however
fact
is that calling Dispose is described in the documentation as a must (
page
202 of the official core reference guide of VB )

So in short if the contract is there you must conform to the contract
and
thus call dispose , you might discuss for yourself if the creator of
the
object did a good job if he / she implemented the interface in a object
that does not use anny unmanaged resources , but this is still no
reasson
not to call dispose on the object .

regards

Michel Posseth [MCP]

It's also in the Framework Design Guidelines book published by
Microsoft Press. But, apparently neither of these official sources is
enough to assuage the debate.

Not that it will matter, but here's another argument for always
calling Dispose. If you think it really doesn't do anything then the
JIT compiler will optimize it out anyway, but if it does, in fact, do
something crucial then you've 1) eliminated one more source of hard to
find bugs or/and 2) made your application perform better. Either way,
what could possibily go wrong by calling Dispose!
 
Yes, I call Close if it is available, Dispose if it is available and then
set the object to nothing
before it goes out of scope.

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.
As I see it, the only open item is whether or not to force garbage
collection.

I don't think that's an open issue at all. I think it's pretty well
established (and benchmarked) that in all but the most rarest of occassions,
this will degrade application performance and is not recommended.

-Scott
 
I have had applications that would not end because an object was still in
existence and the garbage collector
ignored it. Of course this was before .Net so maybe it is safe to rely on
garbage collection...

If it was before .NET, then you didn't experience any Garbage Collector
issues at all, since prior to .NET, was COM architecture, which used
reference counters in order to determine when an object should be destroyed.
..NET doesn't use this approach. COM architecture managed memory in a
"deterministic" way, so you HAD to determine when your objects weould be
destroyed. .NET architecture uses "non-deterministic" memory management,
which is fundamentally different (and in many ways the exact opposite of
COM).

I do understand that old habbits die hard, but you are not gaining anything
and, in fact, could be hurting your application's performance.

-Scott
 
Well, that is exactly the point I'm making. You've made an educated
decision about your need to call dispose. As I stated in an earlier post,
if I know for a fact what Dispose does or doesn't do with a type, I'll call
it accordingly. If I don't, I'll call it to be safe and go get educated.

I do belive that Dispose on a DataSet is there to release any hold it may
have on XML files that it uses to read from/write to, but I could be wrong.

Your wrong. DataSet doesn't even have it's own implementation of dispose -
it's really from it's base class.

The DataSet also does not hold onto any file resources, all of the data is
read into memory and the then released. Basically ReadXml looks like:

Public Function ReadXml (ByVal fileName As String) As XmlReadMode
Dim mode As XmlReadMode

Using reader As New XmlTextReader(fileName)
mode = ReadXml (reader, False)
End Using

Return mode
End Function

Another, empty implementation is something like System.IO.MemoryStream.
Internally, it's a byte array - so, dispose doesn't actually do anything.
But, guess what - I still call it :) Though, not directly - Using (using in
C#)
 
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.

Actually, not any more - the compiler can detect this and actually optimizes
it away (at least in release mode).
I don't think that's an open issue at all. I think it's pretty well
established (and benchmarked) that in all but the most rarest of occassions,
this will degrade application performance and is not recommended.

Yep.
 
If it was before .NET, then you didn't experience any Garbage Collector
issues at all, since prior to .NET, was COM architecture, which used
reference counters in order to determine when an object should be destroyed.
.NET doesn't use this approach. COM architecture managed memory in a
"deterministic" way, so you HAD to determine when your objects weould be
destroyed. .NET architecture uses "non-deterministic" memory management,
which is fundamentally different (and in many ways the exact opposite of
COM).

I do understand that old habbits die hard, but you are not gaining anything
and, in fact, could be hurting your application's performance.

99% of the time it didn't really gain you anything in VB6 for local references
:) There were of course a few corner cases, or places where you might do it
to optimize memory usage - but, for the most part it really didn't matter.
 
That's good to know Tom, thanks. Even still, I stand by my point that, for
me, calling dispose is only done when it does something.

:)

-Scott
 
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
 
But, would this not help in older versions of the Fraework? I still have
clients using 1.x!

-Scott
 
I've followed this thread, carefully I thought, because it's an area which I
know I don't understand well, AND because I have been looking for a memory
leak in a program I've been working on.

But even after reading this thread, and probably because I wasn't reading it
carefully enough, I thought that it was sufficient to set something to
Nothing. But my monitoring of memory usage, always after a GC.Collect,
showed a memory leak. When I changed the "something = Nothing" statement to
"something.Dispose" it made a dramatic difference (in the right direction).

And that's how I learned my lesson!

Bob
 
Back
Top