GC如何在.NET中的静态成员中收集资源?

时间:2010-03-31 19:24:04

标签: c# .net garbage-collection

我有一段这样的代码:

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
    }
}

这可能不是一个好习惯,但我只是想用这个例子来询问解构函数和GC是如何工作的。

我的问题是:Will~Program()会在非确定的时间被调用,或者在这种情况下根本不会被调用。如果不会调用解构器,那么GC如何收集非托管资源和托管资源。

4 个答案:

答案 0 :(得分:1)

你的情况很不清楚,因为如果没有创建一个类的实例就不会调用终结器。

但是,只调用dispose对对象本身的垃圾收集没有任何作用,它只是告诉对象释放任何资源(尤其是句柄等)。因此,如果您希望GC收集实例,则需要将引用设置为null,如果没有其他实例引用,则最终将收集该实例。

基本上每个静态引用都可以看作是根引用,它包含在GC检查实时引用中。所有无法通过实时参考(直接或间接)到达的实例都是候选人。引用“变量”是否为静态无关紧要。

答案 1 :(得分:1)

静态引用将根除实例,直到将其显式设置为null或卸载其程序集。如果这些实例都没有发生,则静态引用指向的实例将保持使用状态,因此不会被收集。如果它不符合垃圾收集条件,则不会调用终结器。

Btw GC只处理托管内存。它不处理非托管资源。为此,您需要IDiposable和/或终结器。

答案 2 :(得分:1)

C#中没有静态终结器(析构函数)。因此,除非实际创建Program的实例,否则永远不会调用 ~Program()

当调用(if)时,它只调用Dispose()的{​​{1}}方法;因为在调用终结器之后仍然保留对StreamReader的引用,所以在程序退出之前,实例永远不会被垃圾收集。

答案 3 :(得分:1)

在卸载AppDomain或进程之前,它可能不会回收这些资源。

如果你永远不会实例化一个对象,它永远不会被销毁。这正是你想要的原因,可能就像Singleton一样。我相信有一种叫做“Phoenix Singleton”的味道,它可以让Singleton得到清理,然后再次需要时重建。您可以使用WeakReference为单例对象实现它。

在任何情况下,对于运行有限时间段的简单程序,我不会担心它,除非它成为一个问题......当进程退出时,资源将被清除。