To answer your question directly -
The Destructor is called by the Garbage collector
The Garbage Collector thread puts the object reference on the finalizer queue, and the finalizer thread calls the finalizer (A.K.A. Destructor). This is why you should implement the IDisposable
interface in the first place.
The using
statement is actually syntactic sugar for try...finally
- When you write
using(var x = new MyDisposableClass())
{
// code here
}
it's the same as writing:
var x = new MyDisposableClass()
try
{
// code here
}
finally
{
(IDisposable(x)).Dispose();
}
So c# calls the Dispose
method of your instance the second it hits the end of the using
block.
However, this does not mean that this instance will get garbage collected that very second. In fact, it can live quite happily in the system until the garbage collector finally gets around to clear it. The Garbage collector runs on it's own thread, and the CLR decides when to activate it. You can activate it by calling GC.Collect()
but that's ill advised in most cases.
Read When is it acceptable to call GC.Collect? for more details.
To add some more background - When you are using unmanaged resources you can release them either by writing code for that in the Dispose(bool)
overload or by writing code for that in the Destructor.
Releasing them in the Dispose(bool)
means you can control when they are released in the calling code (and you usually want to do that as soon as possible).
Releasing them in the Destructor means they only gets released (if and) when the finalizer thread executes the Destructor, meaning you can't control when they are released in your code.
Moreover, writing Destructors correctly is hard. So hard that it's best to avoid doing that in the first place.
In fact, it's so hard that Eric Lippert wrote a few blog posts about that, entitled "When everything you know is wrong".
There is some more helpful information in Reed Copsey's five part blog post series on IDisposable
- starting with IDisposable Part 1 – Releasing Unmanaged Resources.
Bonus reading - Implementing a Dispose method
The Dispose(Boolean) overload
In the second overload, the disposing parameter is a Boolean that indicates whether the method call comes from a Dispose method (its value is true) or from a finalizer (its value is false).
The body of the method consists of two blocks of code:
A block that frees unmanaged resources. This block executes regardless of the value of the disposing parameter.
A conditional block that frees managed resources. This block executes if the value of disposing is true. The managed resources that it frees can include:
Managed objects that implement IDisposable
. The conditional block can be used to call their Dispose implementation. If you have used a safe handle to wrap your unmanaged resource, you should call the SafeHandle.Dispose(Boolean) implementation here.
Managed objects that consume large amounts of memory or consume scarce resources. Freeing these objects explicitly in the Dispose method releases them faster than if they were reclaimed non-deterministically by the garbage collector.
And one last thing - you wrote "I know there is no need for destructor when IDisposable is implemented" - This is almost correct. You almost never should override the destructor for your types, as a good read of Mr. Lipper's blog indicates.