Consider the following code:
namespace DisposeTest
{
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Calling Test");
Test();
Console.WriteLine("Call to Test done");
}
static void Test()
{
DisposeImplementation di = new DisposeImplementation();
}
}
internal class DisposeImplementation : IDisposable
{
~DisposeImplementation()
{
Console.WriteLine("~ in DisposeImplementation instance called");
}
public void Dispose()
{
Console.WriteLine("Dispose in DisposeImplementation instance called");
}
}
}
The Dispose just never get's called, even if I put a wait loop after the Test();
invocation. So that quite sucks. I want to write a class that is straightforward and very easy to use, to make sure that every possible resource is cleaned up. I don't want to put that responsibilty to the user of my class.
Possible solution: use using
, or call Dispose myself(basicly the same). Can I force the user to use a using? Or can I force the dispose to be called?
Calling GC.Collect();
after Test();
doesn't work either.
Putting di
to null
doesn't invoke Dispose either. The Deconstructor DOES work, so the object get's deconstructed when it exits Test()
Ok guys, it's clear now!
Thank you all for your answers! I will add a warning in the comment!
A couple of important points should be made to address the OP's question:
using()
block.Finalizer: Some developers refer to it as a destructor. And in fact it is even called a Destructor in the C# 4.0 Language Spec (section 1.6.7.6) and in previous versions of the current ECMA-334 spec. Fortunately, the 4th Edition (June 2006) correctly defines Finalizers in Section 8.7.9 and attempts to clear up the confusion between the two in Section 17.12. It should be noted that there are important internal differences (no need to go into those gory details here) between what is traditionally known as a destructor and a Destructor/Finalizer in the .NET Framework.
GC.SuppressFinalize()
is not called.GC.Collect(2)
for the 2nd generation of the GC.Finalization: Finalization is the .NET Framework's way to deal with the 'graceful' cleanup and releasing of resources.
While this is certainly more info that you asked for, it provides background on how things work and why they work the way they do. Some people will argue that they shouldn't have to worry about managing memory and resources in .NET, but that doesn't change the fact that it needs to be done - and I don't see that going away in the near future.
Unfortunately, the examples above (mistakenly) imply that you need to implement a Finalizer as part of the standard Dispose pattern. However, you should not implement a Finalizer unless you are using UNmanaged code. Otherwise, there are negative performance implications.
I have posted a template for implementing the Dispose pattern here: How do you properly implement the IDisposable pattern?