hi Cory......
The programmer has no control on when the destructor is going to be executed
because this is determined by the Garbage Collector. The garbage collector
checks for objects that are no longer being used by the application. It
considers these objects eligible for destruction and reclaims their memory.
Destructors are also called when the program exits. When a destructor
executes what is happening behind the scenes is that the destructor
implicitly calls the Object.Finalize method on the object's base class.
Therefore, the preceding destructor code is implicitly translated to:
protected override void Finalize()
{
try
{
// Cleaning up .
}
finally
{
base.Finalize();
}
}
Now, let us look at an example of how destructors are called. We have three
classes A, B and C. B is derived from A, and C is derived from B. Each class
has their own constructors and destructors. In the main of the class App, we
create an object of C.
using System;
class A
{
public A()
{
Console.WriteLine("Creating A");
}
~A()
{
Console.WriteLine("Destroying A");
}
}
class B:A
{
public B()
{
Console.WriteLine("Creating B");
}
~B()
{
Console.WriteLine("Destroying B");
}
}
class C:B
{
public C()
{
Console.WriteLine("Creating C");
}
~C()
{
Console.WriteLine("Destroying C");
}
}
class App
{
public static void Main()
{
C c=new C();
Console.WriteLine("Object Created ");
Console.WriteLine("Press enter to Destroy it");
Console.ReadLine();
c=null;
//GC.Collect();
Console.Read();
}
}
As we expect, the constructors of base classes will be executed and program
will wait for the user to press 'enter'. When this occurs, we set the object
of class C to null. But the destructors are not executing ..!!?? As we
already said, the programmer has no control on when the destructor is going
to be executed because the Garbage Collector determines this. But the
destructors are called when the program exits. You can check this by
redirecting the o/p of the program to a text file. I have the output here.
Notice that the destructors of the base classes are called because behind the
scenes base.Finalize() is called.
Creating A
Creating B
Creating C
Object Created
Press enter to Destroy it
Destroying C
Destroying B
Destroying A
So, what do you do if you want to call the destructors once you are finished
using the object? There are two ways:
Call the Garbage collector to clean up.
Implement Dispose method of IDisposable interface.
Hope this helps in why explicitly calling m.close() does not raise the error
and moreover check these hints also.
Note 1: Do not use destructor if your class does not use native / unmanaged
resources. If you do so, you create unnecessary work for the garbage
collector.
Note 2: If you implement the IDisposable and a destructor, you should call
the Dispose method from the destructor to force the object to release
resources immediately.
Hope the above explanation might be useful for you.
Regds
Kannan.V
Cory Nelson said:
The following code is causing the exception
"System.InvalidOperationException: Handle is not initialized". From my
understanding, objects in a class are expected to be valid during the
destructor.
This is causing the exception (note, if you explicitly call m.Close(),
this does not happen):
public class DbManager {
private readonly SqlConnection con;
public DbManager() {
con=new SqlConnection("Data Source=<source>; User ID=<user>;
Password=<password>;Initial Catalog=<database>");
Open();
}
~DbManager() {
Close();
}
public void Open() {
con.Open();
}
public void Close() {
con.Close();
}
}
static void Main(string[] args) {
DbManager m=new DbManager();
}