destructors

  • Thread starter Thread starter zero
  • Start date Start date
Z

zero

I have recently started to learn C# (from a background of C++ and Java),
and there is something that my textbook is not 100% clear on, so I thought
I'd ask the experts.

Are C# destructors guaranteed to be called like in C++, or are they like
the Java finalize method? And if they are guaranteed to be called before
termination of the program, is the order in which they are called
guaranteed as well?

TIA
zero
 
They are the same thing as the Finalize() function. IOW, they are called by
the Garbage Collector. And yes, they are guaranteed to be
called...eventually.

This is why the IDispose Interface was created. If you don't want to wait
around for the GC, you just call Dispose().

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
A watched clock never boils.
 
They are the same thing as the Finalize() function. IOW, they are called
by the Garbage Collector. And yes, they are guaranteed to be
called...eventually.
I'm not sure they are guaranteed to be called, particularly when you exit
your program.
Anyway if you want to be sure sure your unsused object are called collected
and finalized you can call:
GC.Collect();
GC.WaitForPendingFinalizers();
This is why the IDispose Interface was created. If you don't want to wait
around for the GC, you just call Dispose().
Dispose() and Finalize() are 2 different methods called at different time!
it's advised to write your code like that:

class MyHeavyObject : IDisposable
{
IntPtr aNativeResource;
IDisposable aManagedResource;

public MyHeavyObject() { .... }

~MyHeavyObject()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual bool Dispose(bool disposing)
{
if( disposing )
{
aManagedResource.Dispose();
}

if(aNativeResource != IntPtr.Zero)
Free( aNativeResource);
aNativeResource = IntPtr.Zero;
}
}
 
You are correct. The execution of finalizers has a loose guarentee at
best. .NET 2.0 narrows the circumstances in which the finalizer will
not run with the addition of constrained execution regions (CERs).
Take a look at CriticalFinalizerObject and SafeHandle for more
information.

Brian
 
You are correct. The execution of finalizers has a loose guarentee at
best. .NET 2.0 narrows the circumstances in which the finalizer will
not run with the addition of constrained execution regions (CERs).
Take a look at CriticalFinalizerObject and SafeHandle for more
information.

so basically I'd best stick to a Java-like scheme to close resources etc.
Thanks all for your replies :-)
 
As I mentioned, implementing and using the IDispose interface correctly
takes care of all that.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
A watched clock never boils.
 
Correction: IDisposable!

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
A watched clock never boils.
 
zero said:
so basically I'd best stick to a Java-like scheme to close resources etc.
Thanks all for your replies :-)

It's best to use the IDisposable interface and explicitly call Dispose
yourself. The finalizer (or destructor) is only called by the GC when
a developer forgets or chooses not to call Dispose. The circumstances
in which the GC cannot call the finalizer are rare so it's usually not
a big deal.
 
zero... The equivalent of C++ Resource Acquisition Is Initialization
(RAII) is the automatic calling of IDisposable through the using
construct.

C++
int CheckPort(int p) {
Socket_t mainSock(p); // constructor run
if(mainSock.Check()) return 1;
Socket_t backupSock(p+1); // constructor run
if(backupSock.Check()) return 2;
return 0;
}

C#
int CheckPort(int p) {
using(Socket_t mainSock = new Socket_t(p)) {
if(mainSock.Check()) return 1;
using(Socket_t backupSock = new Socket_t(p+1)) {
if(backupSock.Check()) return 2;
}
}
return 0;
}


Regards,
Jeff
 
Back
Top