There are various problems with the C# 'destructor'.
First, you never know when or if it will be called. So it's not like a C++
destructor, where it gets called the moment the object goes out of scope or
is deleted. It won't be called until a garbage collect occurs. If your
system is not busy right now it could literally be hours before the
destructor runs, even though the object is out of use.
When your application exits, .NET tries to run all finalizers (C#
destructors are really finalizers in disguise), but if it takes more than a
few seconds, it just gives up. So you can never be sure the destructor will
run.
Also, you can't use other finalizable objects from within your destructor.
(I.e. other objects that have destructors.) This is because .NET makes no
guarantees about the order in which it runs finalizers. So it's quite
possible that any objects you were using have already been finalized by the
time your destructor runs. Calling methods on an object whose destructor
has already been run is never a good idea. And since you can't be sure
which ones have been finalized (or indeed which of the objects you are using
even have a finalizer) it's not safe to use objects.
So all of that means that destructors aren't actually a great deal of use.
The main reason for implementing a finalizer is because your object wraps
some kind of raw handle (e.g. a raw Win32 handle, or maybe a handle obtained
through Interop from some unmanaged library) and you need to ensure that it
gets freed. But this is just a safety net, and not a terribly reliable one,
given the limitations mentioned above.
Worse, finalizers cause performance issues. The system has to work harder
to track finalizable objects. Try writing a loop to see how fast you can
create objects without destructors and how fast you can create objects with
destructors - something like this:
int cout = 0;
while (true)
{
new MyClass();
count += 1;
if (count % 10000000 == 0) Console.WriteLine(count);
}
If MyClass does not have a destructor, it creates about 20 million objects a
second on my system. If it does have a destructor, it only manages about 2
million!
Also, finalizers cause objects to hang around in memory very much longer
than they otherwise would, which increases the working set of the process.
So they are best avoided.