Sign in to follow this  
Headkaze

[.net] Using Dispose() in .NET 2.0 / VS 2005

Recommended Posts

Ever since I've moved to VS 2005 when I implement Dispose() all it is is one method. ie.
public void Dispose()
{
}
Because I like to clean up objects manually to free up any memory they are using I clean them up in this method. ie.
public void Dispose()
{
    if (myObject != null)
    {
        myObject.Dipose();
        myObject = null;
    }
}
I just want to clarify if I'm doing the right thing. Is this method only needed for unmanaged objects? Why does implementing IDisposable only have that one simple method, where in VS 2003 it had areas for disposing of managed and unmanaged resources and also had a boolean. ie.
private bool disposed = false;

public void Dispose()
{
	Dispose(true);
	GC.SuppressFinalize(this); // remove this from gc finalizer list
}

private void Dispose(bool disposing)
{
	if (!this.disposed) // dispose once only
	{
		if (disposing) // called from Dispose
		{
			// Clean up managed resources here.
		}

		// Clean up unmanaged resources here.
	}
	disposed = true;
}
So which way should I be using in VS 2005 / .NET 2.0? Is the new automatic implementation of IDisposable enough now? Or should I still be using this last method I've shown?

Share this post


Link to post
Share on other sites
Quote:

Because I like to clean up objects manually to free up any memory they are using I clean them up in this method.


That's too bad, since Dispose doesn't do that. Dispose will close files, drop connections... stuff like that. The GC still owns all memory.

Share this post


Link to post
Share on other sites
Quote:
Original post by Headkaze
I just want to clarify if I'm doing the right thing. Is this method only needed for unmanaged objects?


In general to deterministically release resources i.e. close files, close database connections etc, etc.

Quote:
Original post by Headkaze
Why does implementing IDisposable only have that one simple method, where in VS 2003 it had areas for disposing of managed and unmanaged resources and also had a boolean.


It's never changed, IDisposable interface always had only one method, that code you have there is some recommended example code, the Dispose overload which takes a boolean is a private method of some class, it's completely seperate from IDisposable.Dispose and not treated specially.

Quote:
Original post by Headkaze
So which way should I be using in VS 2005 / .NET 2.0?


You can still use that form if it makes sense for the context, it all depends on the context.

Quote:
Original post by Headkaze
Is the new automatic implementation of IDisposable enough now?


Kind of using the using keyword this saves you from manually (and maybe errornously) placing calls to Dispose combind with scoping e.g


using (SomeDisposableObject sdo = new SomeDisposableObject(...)) {

// do stuff with sdo which is in a valid state (i.e. clean open file, clean open connection, etc, etc)

} // compiler inserts sdo.Dispose(); here

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Quote:

Because I like to clean up objects manually to free up any memory they are using I clean them up in this method.


That's too bad, since Dispose doesn't do that. Dispose will close files, drop connections... stuff like that. The GC still owns all memory.


But if I'm removing a reference to the object then the garbage collector will eventually free up the memory used by the object right? Or is implementing Dispose enough to do that if I just leave the method empty? If I myObject.Dispose() do all references get freed up automatically? Do I even need to Dispose each object reference in the object manually?

Share this post


Link to post
Share on other sites
You only really need to implement Dispose if the object is allocating unmanaged resources which the GC isn't aware of (such as OpenGL contexts). If your managed class only contains managed members then there's no need to implement Dispose, once all references to the class instance are set to null, the GC will eventually clean up the object and decrease the reference counts to member objects automatically, cleaning any members that have a zero reference count and so on.

You really don't need to worry about cleaning objects up - that's a C++ attitude which C# has come to terms with.

Skizz

Share this post


Link to post
Share on other sites
I disagree, slightly ;)

There are cases where you want to Dispose() purely managed objects intentionally. Suppose, for example, your Level class had some events which report the progress while loading the level. Now your LoadingScreen class registers itself to these events to entertain the player with a progress bar while the level is loading. When loading is complete, you should dispose the LoadingScreen instance, thereby letting it unsubscribe from the events of the Level class, otherwise, the GC will still see that your Level references the LoadingScreen and keep the loading screen alive until the Level instance goes down.

Implementing a simple Dispose() method is fine in these cases.

If, on the other hand, you do have unmanaged resources, you should always use the Destructor+IDisposable variant. This will guarantee that, even if you forget to call Dispose() yourself, the unmanaged resource will eventually be reclaimed. Adding a destructor to a class in .NET will, however, incur a slight overhead since now the GC can not just reclaim the object's memory, but has to put its destructor in the finalizer queue and can only collect the object after its finalizer has been called.

The Destructor+IDisposable pattern is much simpler to understand if you replace that disposing parameter with a meaningful name:


class MyClass : IDisposable {

public ~MyClass() {
Dispose(false); // false == not called manually
}

public void Dispose() {
Dispose(true); // true == called manually

// No need to keep this in the finalizer queue anymore
GC.SuppressFinalize(this);
}

public void Dispose(bool calledManually) {
if(calledManually) {
// It is ok to access referenced objects of this class here
// (eg. to Dispose() them as well)
} else {
// Call comes from GC. Destruction order is undefined,
// so do not access any referenced objects here,
// as they might have been destroyed already.
}

// Release unmanaged resources in both cases
}

}

Share this post


Link to post
Share on other sites
Quote:
Original post by Headkaze
Quote:
Original post by Telastyn
Quote:

Because I like to clean up objects manually to free up any memory they are using I clean them up in this method.


That's too bad, since Dispose doesn't do that. Dispose will close files, drop connections... stuff like that. The GC still owns all memory.


But if I'm removing a reference to the object then the garbage collector will eventually free up the memory used by the object right?


Only if you're removing the last reference to the object.

Quote:

Or is implementing Dispose enough to do that if I just leave the method empty?


Dispose has nothing to do with removing references (unless you tell it to, like Cygon).

Quote:

If I myObject.Dispose() do all references get freed up automatically?


No. Dispose does what you write.

Quote:

Do I even need to Dispose each object reference in the object manually?


Yes, if contained objects have network connections or files open or something similar you want to free up. Otherwise the GC will collect them when it's ready (when you have no references to them or their referrers).


Seriously, I've been programming in C# for almost 2 years now and have had to implement Dispose maybe twice. Don't fight the GC.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Seriously, I've been programming in C# for almost 2 years now and have had to implement Dispose maybe twice. Don't fight the GC.


Astonishing, given that, as soon as you reference a class that implements IDisposable in an object variable, you're practically forced to implement IDisposable yourself.

Aside from that, I often have cases where an event publisher outlives its consumers by far. If I wouldn't unsubscribe those consumers when they're disposed, they wouldn't be collected and keep wasting time processing any events they were subscribed to in a zombified state.

I said nothing about cluelessly cleaning up simple references to other objects, so I'm not happy receiving a side blow for that. Yet, even such practice can *sometimes* help the GC on platforms where no generational GC is available (like the XBox 360, which is relevant since the original poster is at least active in the XNA community). Of course the usual disclaimer about premature optimization should come to mind here :)

There's a very enlightening post by Shawn Hargreaves about making good use of the garbage collector for real-time applications:
Shawn Hargreaves Blog: Twin paths to garbage collector nirvana

-Markus-

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this