2004-09-22
Static destructor in C#
C# (and .NET in general) offers static constructors for classes, but why are there no static destructors? I needed such a static destructor for a class that had to clean up resources. So I created a little helper-class that adds static destructor-functionality to a class:
public delegate void DestructorDelegate();
public class Destructor
{
private DestructorDelegate destructorMethod;
public Destructor(DestructorDelegate method)
{
destructorMethod = method;
}
~Destructor()
{
if (destructorMethod != null) destructorMethod();
}
}
Here's an example that shows how to use it:
public class MyClass
{
private static Destructor myDestructor;
static MyClass()
{
DestructorDelegate destructorMethod;
destructorMethod = new DestructorDelegate(this.Destroy);
myDestructor = new Destructor(destructorMethod);
}
private static void Destroy()
{
// this is the static destructor-method
}
}
Updated Nov. 4th 2005: bug fix, thanks to mIKEL.
Comments:
Post a Comment
Links to this post:
Tommy, Your code didn't work. Because, first you cannot call this in a static method. second, with out knowledge of .Net Runtime, the only way MyClass knows when to call static destructor is to remember all the instances and call static destructor right after destroy the last instance. The following is event more simple code to implement static destructor.
public class MyClass
{
static System.Collections.Hashtable hashtable = new System.Collections.Hashtable();
public MyClass()
{
if (hashtable.Count== 0)
{
System.Console.WriteLine("Static Constructor");
}
hashtable.Add(this,this);
System.Console.WriteLine("Constructor");
}
~MyClass()
{
hashtable.Remove(this);
System.Console.WriteLine("Destructor");
if (hashtable.Count == 0)
{
System.Console.WriteLine("Static Destructor");
}
}
}
public class MyClass
{
static System.Collections.Hashtable hashtable = new System.Collections.Hashtable();
public MyClass()
{
if (hashtable.Count== 0)
{
System.Console.WriteLine("Static Constructor");
}
hashtable.Add(this,this);
System.Console.WriteLine("Constructor");
}
~MyClass()
{
hashtable.Remove(this);
System.Console.WriteLine("Destructor");
if (hashtable.Count == 0)
{
System.Console.WriteLine("Static Destructor");
}
}
}
I just tested it again, and it still works.
The static destructor of your class is called when the application is closed (logically, it should be when the class unloads).
The static destructor of your class is called when the application is closed (logically, it should be when the class unloads).
I found a best solution..
using System;
public class MyClass
{
private static readonly MyClass instance = null;
static MyClass()
{
Console.WriteLine("static constructor");
instance = new MyClass();
}
public MyClass()
{
Console.WriteLine("constructor");
}
~MyClass()
{
Console.WriteLine("destructor");
}
}
using System;
public class MyClass
{
private static readonly MyClass instance = null;
static MyClass()
{
Console.WriteLine("static constructor");
instance = new MyClass();
}
public MyClass()
{
Console.WriteLine("constructor");
}
~MyClass()
{
Console.WriteLine("destructor");
}
}
Xiaochen Du, you are wrong too.
If you are using hash table to hold references to objects (in your case to "MyClass" instances), then these instances would never get to their destructor (finalize method).
This happens because the GC (Garbage collector) thinks that these instances still in used - WHY? because the refernce whithin the hash table cause GC to think so.
If you are using hash table to hold references to objects (in your case to "MyClass" instances), then these instances would never get to their destructor (finalize method).
This happens because the GC (Garbage collector) thinks that these instances still in used - WHY? because the refernce whithin the hash table cause GC to think so.
Try using weak references in your collection instead. They won't prevent the garbage collector invoking the finalization member and recovering the instance's memory.
Tommy, good idea to do static destructors! sometimes are needed :-) It would be much better to be one in c#, but it is not...so your idea is fine!
one only note: you define your static constructor as public static, at least in my compiler this does not work, it must be defined as static MyClass(){...}
one only note: you define your static constructor as public static, at least in my compiler this does not work, it must be defined as static MyClass(){...}
Links to this post:

