D
Daniel O'Connell [C# MVP]
pronto said:Hello All.
I've got some unexpected (to me) behavior. In C++, destructor of the class
that wasn't created is not called,
in C# some how I've got destructor call for class that wasn't initialized
properly (by constructor). Please look examples.
Is that a normal ? .. or garbage collector take care of all ?
Am I doing something wrong ?
It can happen. At the moment you create an object, it exists. The
constructor does initialization, but if it throws an exception, you end up
with a partially constructed type which the GC will eventually clean up.
Finalization is also handled by the GC and will always be called for a given
instance, so it *must* be able to deal with partially constructed instances.
In most cases there is no point in using a finalizer, the GC will always
clean up managed memory. You need finalization when you are wrapping
unmanaged resources like file handles. Finalization is something you should
strive to avoid, it can be very expensive and not totally reliable(there are
a small set of circumstances where finalizers may not be run, though they
are rather rare in practice and can be pretty much eliminated with .NET 2.0,
once its released). Look up the IDisposable pattern(its not quite as easy as
RAII, but with the using keyword it works well), joining IDisoposable with
GC.SurpressFinalize can help performance substantially.
Also, if you are interested in why finalization is expensive and a bit of
how it works and feel like reading alot, check out
http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx (second time
I've linked to that today, LOL).
P.S. I'm new in C#.
C++ output :
------------
C1::C1
C2::C2
C1::~C1
Exception!
Press any key to continue
C# output :
-----------
C1::C1
C2::C2
Exception!
C3::~C3
C2::~C2
C1::~C1
Press any key to continue
C++ code :
----------
class C1
{
public:
C1::C1()
{
puts("C1::C1");
}
virtual C1::~C1()
{
puts("C1::~C1");
}
};
class C2 : public C1
{
public :
C2::C2()
{
puts("C2::C2");
throw "1";
}
virtual C2::~C2()
{
puts("C2::~C2");
}
};
class C3 : public C2
{
public :
C3::C3()
{
puts("C3::C3");
}
virtual C3::~C3()
{
puts("C3::~C3");
}
};
int main(int argc, char* argv[])
{
try
{
C3 c3;
}
catch(...)
{
puts("Exception!");
}
return 0;
}
C# code :
---------
class C1
{
public C1()
{
Console.WriteLine("C1::C1");
}
~C1()
{
Console.WriteLine("C1::~C1");
}
};
class C2 : C1
{
public C2()
{
Console.WriteLine("C2::C2");
throw new Exception("1");
}
~C2()
{
Console.WriteLine("C2::~C2");
}
};
class C3 : C2
{
public C3()
{
Console.WriteLine("C3::C3");
}
~C3()
{
Console.WriteLine("C3::~C3");
}
};
class Class1
{
[STAThread]
static void Main(string[] args)
{
try
{
C3 c3 = new C3();
}
catch(Exception)
{
Console.WriteLine("Exception!");
}
}
}