为什么没有收集未引用的对象?

时间:2015-07-17 04:57:15

标签: c# mono

此程序打印" True"控制台。

分配一个对象,对其进行WeakReference,转到块范围之外,然后检查WeakReference.IsAlive。

public static void Main (string[] args)
{
    Test ();
}

static void Test ()
{
    WeakReference wref = null;

    { // block scope
        var obj = new object ();
        wref = new WeakReference (obj);
    }

    // obj is out of scope
    // Console.WriteLine (obj);

    GC.Collect ();

    Console.WriteLine (wref.IsAlive); // => True
}

为什么不收集obj,虽然obj不在范围内?

该程序由Mono 3.12.0编译。

修改

抱歉,不恰当的例子。

以下程序也会打印True。块范围似乎没有关系。 使用调试模式尝试

    public static void Main (string[] args)
    {
        Test ();
    }

    static void Test ()
    {
        WeakReference wref = null;

        var obj = new object ();
        wref = new WeakReference (obj);
        obj = null;

        GC.Collect ();

        Console.WriteLine (wref.IsAlive); // => True
    }
$ mcs -debug- Program.cs
$ mono Program.exe

3 个答案:

答案 0 :(得分:2)

因为您在调试器中运行,我猜。

尝试运行发布版本,并在调试器外部手动运行。

答案 1 :(得分:1)

如果不是GC,您希望GC具有100%的确定性。

可能发生的一些事情:

  • JIT优化了空分配。
  • 指向实例的指针可以留在临时堆栈位置或寄存器中(您调用函数,传递变量,将变量放在某些体系结构的寄存器中)。

答案 2 :(得分:0)

在GC.Collect之后,添加:

GC.WaitForPendingFinalizers(); 

通过调用此过程,所有可终结对象都可以在继续执行程序之前执行任何必要的清理。它确保您的代码不会调用当前正在销毁的对象的方法。