views:

115

answers:

4

I have a piece of code like this:

Class Program
{
    static StreamReader sr = null;
    static int var=0;
    static Program()
    {
        sr = new StreamReader("input.txt")
    }

    ~Program()
    {
        sr.Dispose();
    }

    static void main(string args[])
    {
        //do something with input here
    }
}

This may not be a good practice, but I just want to use this example to ask how the deconstructor and GC works.

My question is: Will ~Program() get called at a non-determined time or it won't be called at all in this case. If the deconstructor won't get called, then how GC collect the unmanaged resources and managed resources.

+1  A: 

Your case is quite unclear, as the finalizer would not be called without creating an instance of the class.

However, only calling dispose does nothing towards garbage collection of the object itself, it merely tells the object to release any resource (especially handles etc.). So if you want the GC to collect the instance, you need to set the reference to null, and if there is no other live reference to the instance it will eventually be collected.

Basically each static reference can be seen as root reference, which is included in the GC checks for live references. All instances which cannot be reached through a live reference (directly or indirectly) are candidates for collection. It does not matter if the reference "variable" was static or not.

Lucero
+1  A: 

A static reference will root an instance until it is explicitly set to null or its assembly is unloaded. If neither of these happens the instance a static reference points to will remain in use and thus will not be collected. If it isn't eligible for garbage collection its finalizer will not be called either.

Btw GC only handles managed memory. It doesn't handled unmanaged resources. For that you need IDiposable and/or finalizers.

Brian Rasmussen
+1  A: 

There is no such thing as a static finalizer (destructor) in C#. Therefore, unless an instance of Program is ever actually created, ~Program() will never be called.

When (if) it is called, it only calls the Dispose() method of the StreamReader; because a reference to the StreamReader is still retained after the finalizer is called, the instance will never be garbage collected until the program exits.

Randolpho
+1  A: 

It probably wouldn't reclaim those resources until the AppDomain or process is unloaded.

If you never instantiate an object, it will never be destroyed. This is exactly why you want, probably something like a Singleton. I believe there is a flavor called "Phoenix Singleton," that will allow a Singleton to be cleaned up and then rebuilt when it is needed again. You could implement it using a WeakReference to the singleton object.

In any case, for a simple program that runs for a bounded period of time, I wouldn't worry about it unless it becomes a problem... the resources will be cleaned up when the process exits.