我正在尝试使用WeakReference类,但我没想到它不会将对象保留在下一个垃圾收集中。为什么?
我不了解这门课程的实际用途。
在将myObject设置为null后,代码强制执行另一个垃圾回收。
编辑:在else的结尾如果没有处理myObject的行,是因为编译器知道WeakReference wr对象仍然在代码中使用,以便垃圾收集不回收它?
class Program
{
static void Main(string[] args)
{
MyObject myObject = new MyObject(25);
WeakReference wr = new WeakReference(myObject);
if (wr.IsAlive) Console.WriteLine("Alive");
myObject = null;
GC.Collect();
if (wr.IsAlive) Console.WriteLine("Still alive");
else if(!wr.IsAlive) Console.WriteLine("Dead");
//
//edit: added this
GC.Collect();
if (wr.IsAlive) Console.WriteLine("Still alive");
else if (!wr.IsAlive) Console.WriteLine("Dead");
//edit end
Console.ReadKey();
}
}
class MyObject : IDisposable
{
private bool disposed = false;
private int id = 0;
public MyObject(int id)
{
this.id = id;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
Console.WriteLine("disposed {0}", id);
if (!disposed)
{
if (disposing)
{
//free managed
}
//free unmanaged
disposed = true;
}
}
~MyObject()
{
Dispose(false);
}
}
在else的结尾如果行没有处理
myObject
,是因为编译器知道WeakReference
wr
对象仍然在代码中使用,以便垃圾收集不回收它?
不,这是因为您运行了附加调试器的应用程序。请阅读@Hans Passant的答案here了解详情。
如果您在发布模式下构建应用程序并在没有附加调试器的情况下运行它,您应该会在控制台上看到“Alive”,“Dead”和“Dead”。我做。
您还应该从MyObject
类中删除终结器,因为您没有使用非托管资源。
简短回答为什么你的对象不能在第一个集合中存活:有两种类型的弱引用:short和long。短期收集立即收集,只有当它们的终结器完成时才收集 - 这是一个很长的弱引用应该有终结器,这对你的情况是正确的,但另一个强制要求是它应该用trackResurrection
参数设置为true
(默认为false
) )。终结器在第二次收集期间执行,但是当trackResurrection
设置为false
时,对象不会被跟踪,并且它的引用被设置为null(但是正式它直到最终化仍然存在但无法访问)。