The responses to this question have got more than a little confused.
The title asks about disposal, but then says that they want memory back immediately.
.Net is managed, which means that when you write .Net apps you don't need to worry about memory directly, the cost is that you don't have direct control over memory either.
.Net decides when it's best to clean up and free memory, not you as the .Net coder.
The Dispose
is a way to tell .Net that you're done with something, but it won't actually free up the memory until it's the best time to do so.
Basically .Net will actually collect the memory back when it's easiest for it to do so - it's very good at deciding when. Unless you're writing something very memory intensive you normally don't need to overrule it (this is part of the reason games aren't often written in .Net yet - they need complete control)
In .Net you can use GC.Collect()
to force it to immediately, but that is almost always bad practise. If .Net hasn't cleaned it up yet that means it isn't a particularly good time for it to do so.
GC.Collect()
picks up the objects that .Net identifies as done with. If you haven't disposed an object that needs it .Net may decide to keep that object. This means that GC.Collect()
is only effective if you correctly implement your disposable instances.
GC.Collect()
is not a replacement for correctly using IDisposable.
So Dispose and memory are not directly related, but they don't need to be. Correctly disposing will make your .Net apps more efficient and therefore use less memory though.
99% of the time in .Net the following is best practice:
Rule 1: If you don't deal with anything unmanaged or that implements IDisposable
then don't worry about Dispose.
Rule 2: If you have a local variable that implements IDisposable make sure that you get rid of it in the current scope:
//using is best practice
using( SqlConnection con = new SqlConnection("my con str" ) )
{
//do stuff
}
//this is what 'using' actually compiles to:
SqlConnection con = new SqlConnection("my con str" ) ;
try
{
//do stuff
}
finally
{
con.Dispose();
}
Rule 3: If a class has a property or member variable that implements IDisposable then that class should implement IDisposable too. In that class's Dispose method you can also dispose of your IDisposable properties:
//rather basic example
public sealed MyClass :
IDisposable
{
//this connection is disposable
public SqlConnection MyConnection { get; set; }
//make sure this gets rid of it too
public Dispose()
{
//if we still have a connection dispose it
if( MyConnection != null )
MyConnection.Dispose();
//note that the connection might have already been disposed
//always write disposals so that they can be called again
}
}
This isn't really complete, which is why the example is sealed. Inheriting classes may need to observe the next rule...
Rule 4: If a class uses an unmanaged resource then implement IDispose and add a finaliser.
.Net can't do anything with the unmanaged resource, so now we are talking about memory. If you don't clean it up you can get a memory leak.
The Dispose method needs to deal with both managed and unmanaged resources.
The finaliser is a safety catch - it ensures that if someone else creates and instance of your class and fails to dispose it the 'dangerous' unmanaged resources can still be cleaned up by .Net.
~MyClass()
{
//calls a protected method
//the false tells this method
//not to bother with managed
//resources
this.Dispose(false);
}
public void Dispose()
{
//calls the same method
//passed true to tell it to
//clean up managed and unmanaged
this.Dispose(true);
//as dispose has been correctly
//called we don't need the
//'backup' finaliser
GC.SuppressFinalize(this);
}
Finally this overload of Dispose that takes a boolean flag:
protected virtual void Dispose(bool disposing)
{
//check this hasn't been called already
//remember that Dispose can be called again
if (!disposed)
{
//this is passed true in the regular Dispose
if (disposing)
{
// Dispose managed resources here.
}
//both regular Dispose and the finaliser
//will hit this code
// Dispose unmanaged resources here.
}
disposed = true;
}
Note that once this is all in place other managed code creating an instance of your class can just treat it like any other IDisposable (Rules 2 and 3).