views:

517

answers:

8

Is there any sense to set custom object to null(Nothing in VB.NET) in the Dispose() method? Could this prevent memory leaks or it's useless?!

Let's consider two examples:

public class Foo : IDisposable
{
    private Bar bar; // standard custom .NET object

    public Foo(Bar bar) {
        this.bar = bar;
    }
    public void Dispose() {
        bar = null; // any sense?
    }
}

public class Foo : RichTextBox
{
    // this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object
    private Bitmap backImage; 

    public Foo(Bitmap backImage) {
        this.backImage = backImage;
    }

    protected override void Dispose(bool disposing) {
        if (disposing) {
            backImage = null;  // any sense?
        }
    }
}
+13  A: 

The purpose of Dispose() is to allow clean up of resources not handled by the garbage collector. Objects are taken care of by GC, so there's really no need to do it.

Brian Rasmussen
In my second example I have a Bitmap, that is recommended to Dispose(). Now, as the Bitmap is not created by the object Foo but just passed in parameter, I can't do it. I thought set it at least to Null...
serhio
You always have to decide where clean up of dependencies takes place. If you know that the bitmap isn't used anywhere else, Foo should call `Dispose()`. Otherwise it should just leave it and let the caller handle the clean up. There's no additional benefit in setting the local reference to null. When the instance of Foo is reclaimed so is the instance of Bitmap unless the caller still holds a reference to it.
Brian Rasmussen
@serhio - if you want to free up resources used by your Bitmap object as soon as you're done using it in Foo (no one else is using it), then Foo.Dispose should call backImage.Dispose
Gishu
Perhaps this refers also to heavy objects like TCP Sockets, SQL connections etc?As I just don't know when designing my Foo object will or will not be my "heavy object" externally used, perhaps I can't call Dispose.
serhio
@serhio - that's correct, only call `Dispose` on an object that is "owned" entirely by your class.
Daniel Earwicker
A: 

The purpose of the dispose() is to cleanup the resources that are unmanaged. TCP connections, database connections and other database objects and lots of such unmanaged resources are supposed to be released by the developer in the dispose method. So it really makes sense.

Kangkan
for both examples with a GDI+ Bitmap and a simple custom .NET object Bar? I don't dispose them, cause passed in parameter and not created by the object.
serhio
+8  A: 

Personally I tend to; for two reasons:

  • it means that if somebody has forgotten to release the Foo (perhaps from an event) any downstream objects (a Bitmap in this case) can still be collected (at some point in the future - whenever the GC feels like it); it is likely that this is just a shallow wrapper around an unmanaged resource, but every little helps.
    • I really don't like accidentally keeping an entire object graph hanging around just because the user forgot to unhook one event; IDisposable is a handy "almost-kill" switch - why not detach everything available?
  • more importantly, I can cheekily now use this field to check (in methods etc) for disposal, throwing an ObjectDisposedException if it is null
Marc Gravell
How often do you keep references to objects after calling Dispose() on them?
Brian Rasmussen
@Brian - note the words "accidentally" and "event"; and note that **I'm** not necessarily the person writing the code that *uses* my component. I can't fix *their* code, but I can make mine well-behaved.
Marc Gravell
@Dave - clarified
Marc Gravell
Sorry, if that came out wrong. I am not objecting to the practice. I just prefer the slightly simpler code without these redundancies.
Brian Rasmussen
I'm assuming this is something you do if you need to implement IDisposable anyway (some specific resource needs to be freed) and so you might as well be thorough. Presumably you aren't implementing IDisposable everywhere so you can do this.
MarkJ
+1  A: 

It's just about useless. Setting to NULL back in the old COM/VB days, I believe, would decrement your reference count.

That's not true with .NET. When you set bar to null, you aren't destroying or releasing anything. You're just changing the reference that bar points to, from your object to "null". Your object still exists (though now, since nothing refers to it, it will eventually be garbage collected). With few exceptions, and in most cases, this is the same thing that would have happened had you just not made Foo IDisposable in the first place.

The big purpose of IDisposable is to allow you to release unmanaged resources, like TCP sockets or SQL connections, or whatever. This is usually done by calling whatever cleanup function the unmanaged resource provides, not by setting the reference to "null".

Dave Markle
OK, what if instead *Bar* I have a *TCP socket*? Should it be useless to set it to null? cause it's passed by parameter and "somebody" could use this object...
serhio
Yes, it would be useless. If you had a TCP socket, you would free it up by calling the socket's .Close() method. Same thing goes with SQL Connections. Setting to "null" actually does nothing but change your reference to the object you're using.
Dave Markle
-1, setting to nothing allows garbage collector to clean up on first pass.
AMissico
@AMissico: setting to nothing as opposed to letting it fall out of scope? That would only matter if it was in-scope but unused for a long period of time.
John Saunders
Falling out of scope happens when the object is cleaned up, not when Dispose is called. Therefore, setting to nothing helps, especially for short-lived objects as Aaronaught pointed out.
AMissico
@AMissico: falling out of scope happens when the reference falls out of scope. At the end of a method for a local variable, for instance.
John Saunders
@John Saunders, you are killing me. :O)
AMissico
@AMissico: I'm so tempted to just come back with, "you don't know what you're talking about". But instead, you might want to read a good book on the CLR to educate yourself. I recommend Jeff Richter's excellent "CLR via C#".
Dave Markle
+1  A: 

This can make sense if you want to somehow prevent the disposed owned instance to be re-used.

When you set references to disposable fields to null, you are guaranteed to not use the instances any more.

You will not get ObjectDisposedException or any other invalid state caused by using owned disposed instance (you may get NullReferenceException if you do not check for nulls).

This may not make sense to you as long as all IDisposable objects have a IsDisposed property and/or throw ObjectDisposedException if they are used after they are disposed - some may violate this principle and setting them to null may prevent unwanted effects from occuring.

Marek
+1  A: 

In C# setting an object to null is just release the reference to the object.

So, it is theoretically better to release the reference on managed objects in a Dispose-Method in C#, but only for the possibility to the GC to collect the referenced object before the disposed object is collected. Since both will most likely be collected in the same run, the GC will most propably recognize, that the referenced object is only referenced by a disposed type, so both can be collected.

Also the need to release the reference is very small, since all public members of your disposable class should throw an exception if the class is alreay disposed. So no access to your referenced object would success after disposing the referenced method.

BeowulfOF
Thx Dave, changed the info about VB.NET
BeowulfOF
So, what is the difference between C# and VB.NET when setting Nothing? I exposed the question in C# for readability, but my real project is in VB.NET.
serhio
For your purposes, there is no difference. But VB.NET is a horrible language. In VB.NET, if you set Dim x as integer = nothing, and then print the value of "x", you get 0. In C# it just doesn't compile because "int" is a value type and "null" is strictly a reference. So they don't behave exactly the same. But for reference types like IDisposable objects, they behave the exact same way.
Dave Markle
A: 

In VB.NET there is sense to set to Nothing declared Private WithEvents objects.

The handlers using Handles keyword will be removed in this way from these objects.

serhio
A: 

Following this topic, is there any sense in doing this?

Foo bar = new Foo();
bar.Dispose();
bar = null;

And what if it was an Unmanaged resource?

Francisco Silva
1) If Foo is an unmanaged resource And bar is used only by this class, you should do it(without = null). 2) If you are in VB.NET and bar is declared WithEvents, see my answer, you should do it with = Nothing.
serhio
This is really a different question and so shouldn't be posted in an answer... If `bar` was a field, it is practically *essential* to set it to `null`, so you can logically detect the fact that it has been disposed when future method calls try to access the same `bar` field.
Daniel Earwicker
@Earwicker: setting it to null only proves it's set to null. It doesn't prove it's been disposed.
John Saunders
@John Saunders - obviously. That's why I said "detect", instead of "prove". The coder has to get it right, but by leaving a dangling reference to a disposed object they are merely making harder for themselves to get it right. An object should not be used after it has been disposed (all its methods apart from `Dispose` can/should throw). So it is vital for the owner of the object to distinguish between the two states. The nullity of the field is an ideal way to track that information. Is that any clearer?
Daniel Earwicker