我有一段这样的代码:
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如何收集非托管资源和托管资源。
答案 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
为单例对象实现它。
在任何情况下,对于运行有限时间段的简单程序,我不会担心它,除非它成为一个问题......当进程退出时,资源将被清除。