'Set Object = Nothing'... do you still do this in VB.net????

A

Alan Mailer

I'm relatively new to VB.net. Is it good practice to 'destroy'
created objects... or does VB.net take care of this for you in its
'garbage' collection.

For example, in VB6 we used to have to do a lot of the following:

Set myObject = Nothing

....after we were finished using myObject. Is this still good practice
in VB.net?

Thanks in advance.
 
S

Stephany Young

You will get as many different answers as ther are programmers, however, the
short answer is No.

Now let me qualify that.

No, you are not required to assign Nothing to an object to 'destroy' it.

In general, when an object goes 'out of scope' it will become available for
garbage collection and the Garbage Collector will 'clean it up' when it gets
around to it.

There are some classes in the Framework where you MUST 'destroy' an instance
of it yourself. Off the top of my head, the WebRequest class is one.

Some classes expose a Dispose method. This indicates that an instance of the
class may make use of some unmanaged resources that need to be cleaned up.
For such objects you need to call the Dispose method of the object rather
than assigning Nothing to the object.

My recommendation is to NOT explicity 'destroy' objects at this stage of
your learning curve.

As you progress you will soon learn which objects you need to 'destroy'
whether it be by assigning Nothing or calling the Dispose method.

That said, you are free to explicity 'destroy' objects, a'la VB6, if you so
choose.
 
J

Jon Skeet [C# MVP]

That said, you are free to explicity 'destroy' objects, a'la VB6, if you so
choose.

Just be aware that it won't actually do anything. In particular,
setting a variable's value to Nothing *doesn't* prompt the garbage
collector to collect the object the variable previously referred to.
 
S

Stephany Young

Tru Jon, but it does set it to Nothing which is useful in may ways,
including (for example):

Dim _object As Object = "ABC"

If _x then
_object = Nothing
...
End If

If _object Is Nothing Then Call GiveThatManACigar()
 
J

Jon Skeet [C# MVP]

Stephany Young said:
Tru Jon, but it does set it to Nothing which is useful in may ways,
including (for example):

Dim _object As Object = "ABC"

If _x then
_object = Nothing
...
End If

If _object Is Nothing Then Call GiveThatManACigar()

Oh sure - but it's important that people don't think that setting a
variable to nothing is in any way the same thing as "destroying an
object".
 
A

Andrew Morton

Stephany said:
There are some classes in the Framework where you MUST 'destroy' an
instance of it yourself. Off the top of my head, the WebRequest class
is one.

Assuming that is correct for the WebRequest class, how do you tell? There is
nothing I can see in the docs (framework 1.1) to say that must be done,
whereas, for example, System.Drawing.Bitmap has a Dispose() method, although
I suppose you have to infer from the existence of a Dispose() method that it
needs to be called.

Andrew
 
J

Jon Skeet [C# MVP]

Andrew Morton said:
Assuming that is correct for the WebRequest class, how do you tell? There is
nothing I can see in the docs (framework 1.1) to say that must be done,
whereas, for example, System.Drawing.Bitmap has a Dispose() method, although
I suppose you have to infer from the existence of a Dispose() method that it
needs to be called.

You need to know that the class implements IDisposable. WebRequest was
an unfortunate example, as unfortunately it *doesn't* require disposal,
not implementing IDisposable.

WebReponse, however, is a reasonable example.
 
A

Andrew Morton

Jon said:
You need to know that the class implements IDisposable. WebRequest was
an unfortunate example, as unfortunately it *doesn't* require
disposal, not implementing IDisposable.

Phew! I was getting worried there - I thought maybe there were classes that
need to be disposed of yet no documentation saying so!
WebReponse, however, is a reasonable example.

Hmmm... in that particular case, doesn't WebResponse.Close take complete
care of making it available for GC once it's gone out of scope? I see that
WebResponse implements IDisposable but has no Dispose() method, and I
haven't seen a memory leak in my ASP.NET application.

Andrew
 
S

Stephany Young

I said that WebRequest was off the top of my head.

It was actuallly WebResponse as Jon pointed out.

The documentation for the WebResponse.Close method explicity states (in the
remarks) that the instance must be closed to avoid running out of system
resources.

That's the only one I have encountered however I would find it difficult to
accept that, among the thousand's of classes in the Framework, there are not
other classes with a similar note.

One thing I am not going to do is go and find them for the sake of it.
 
A

Andrew Morton

Stephany said:
I said that WebRequest was off the top of my head.

It was more that I thought the documentation might have left out an
important point, rather than thinking that you were mistaken.
It was actuallly WebResponse as Jon pointed out.

The documentation for the WebResponse.Close method explicity states
(in the remarks) that the instance must be closed to avoid running
out of system resources.

It's a shame it doesn't state that in the constructor documentation, which
would seem to me to be a logical place to mention it. ("After using an
instance of this class, make sure you call its Close method." or similar.)
After all, if you're looking at the docs for Close, you've (well me, anyway)
probably already decided you need to call close.
That's the only one I have encountered however I would find it
difficult to accept that, among the thousand's of classes in the
Framework, there are not other classes with a similar note.

One thing I am not going to do is go and find them for the sake of it.

Me neither! It's just that I'd seen your comment and thought uh-oh!
regarding some of my code. As it was, I had used Close only on the Stream
from a WebRequest rather than using Close on the WebResponse, although I had
seen no ill effects such as a memory leak or running out of resources.

Andrew
 
J

Jon Skeet [C# MVP]

Andrew Morton said:
Phew! I was getting worried there - I thought maybe there were classes that
need to be disposed of yet no documentation saying so!


Hmmm... in that particular case, doesn't WebResponse.Close take complete
care of making it available for GC once it's gone out of scope?

If you use a using statement (in C#) which automatically calls Dispose,
you don't need to explicitly call Close, which makes life easier. Don't
forget that if you want to call Close you need to do it in a finally
block to make sure it gets executed whatever happens.

Making something eligible for garbage collection often isn't enough -
you may need the resources again before the GC gets round to tidying
things up.
I see that WebResponse implements IDisposable but has no Dispose() method

It has a dispose method somewhere - whether it's in the base class, or
implemented explicitly I can't remember off the top of my head. It
couldn't implement IDisposable otherwise though.
 
H

hpassant

When "myObject" is a local variable of your subroutine, it is actually
a bad practice to set it to Nothing at the end of the body. That is
equivalent to calling GC.KeepAlive(). It prevents the object from
getting collected as early as it can be if the collection happens to
start just as the subroutine is busy executing but the remainder of
the body has no more references to the variable.

The garbage collector is smart enough to know when a live reference to
object is itself no longer alive so that both the object containing
the reference as well as the object itself can be collected. There's
no need to help it by setting the reference to Nothing/null. That
also alleviates the pain of having to write try / finally blocks to
set the references to null. The only exception I can think of is when
the object reference is a field of a class and the reference is
temporary.

Forgetting to call Dispose() when a class implements it is not
something you'd typically notice. Your app just runs a bit "heavy",
holding on to unmanaged operating system resources longer than
necessary. After a garbage collection occurs, the finalizer ensures
the Dispose code runs to release the resources. Note however that you
do risk OOM, particularly when you use an object that uses lots of
unmanaged memory but very little GC heap space. Bitmap is a good
example. The one and only example I know of where not calling
Dispose() causes a leak: using a BindingSource on a Windows Forms
dialog and not calling Dispose() on the form after ShowDialog()
returns.
 
J

Jon Skeet [C# MVP]

When "myObject" is a local variable of your subroutine, it is actually
a bad practice to set it to Nothing at the end of the body. That is
equivalent to calling GC.KeepAlive(). It prevents the object from
getting collected as early as it can be if the collection happens to
start just as the subroutine is busy executing but the remainder of
the body has no more references to the variable.

Unless VB.NET is doing something different to C#, it makes no
difference in release mode. The GC/JIT is clever enough to realise
that there will be no more *reads* of the variable - the can be
collected before the assignment is made.

Here's a sample app which shows this:

using System;

class Test
{
~Test()
{
Console.WriteLine("Finalizer called");
}

static void Main()
{
Console.WriteLine ("Before creation");
Test t = new Test();

GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine ("Before assignment");
t = null;
}
}

Forgetting to call Dispose() when a class implements it is not
something you'd typically notice. Your app just runs a bit "heavy",
holding on to unmanaged operating system resources longer than
necessary. After a garbage collection occurs, the finalizer ensures
the Dispose code runs to release the resources. Note however that you
do risk OOM, particularly when you use an object that uses lots of
unmanaged memory but very little GC heap space. Bitmap is a good
example. The one and only example I know of where not calling
Dispose() causes a leak: using a BindingSource on a Windows Forms
dialog and not calling Dispose() on the form after ShowDialog()
returns.

Memory is just one resource, however. More importantly, failure to
dispose of streams and database connections can leave files locked and
use pooled connections way beyond the desired time.

Basically, it's important to call Dispose, and shouldn't be thought of
as an optional extra.

Jon
 
P

Parikshit Sehgal

I'm relatively new to VB.net. Is it good practice to 'destroy'
created objects... or does VB.net take care of this for you in its
'garbage' collection.

For example, in VB6 we used to have to do a lot of the following:

Set myObject = Nothing

...after we were finished using myObject. Is this still good practice
in VB.net?

Thanks in advance.

Alan,

You will find lot of discussion on this.... But as per my exp. there
is no use to setting object = Nothing in VB.NET
The only advantage (May be) is after you set the object = Nothing its
reference count will be reseted to 0 which makes this object as best
candidate to be collected by GC...

So while working with VB.NET there is no use to setting object =
nothing...But keep in mind.. if object is expensive then its better to
dispose the object.

Setting object = Nothing doesnot gurantee that it will be collected
by GC sooon

Parikshit
 
J

Jon Skeet [C# MVP]

The only advantage (May be) is after you set the object = Nothing its
reference count will be reseted to 0 which makes this object as best
candidate to be collected by GC...

No - because objects *aren't reference counted*.

The only use is if you're within a loop or some other construct where
the JIT can't tell that you're not going to use the object again. For
instance (C# code, same applies in VB):

// Large object only needed in the first iteration of the loop
SomeObject foo = new SomeObject();
bool firstTime = true;

// Potentially long running loop
while (ReadData())
{
if (firstTime)
{
foo.DoSomething();
firstTime = false;
foo = null;
}
}

Jon
 

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

Top