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

Why an unreferenced object is not collected?

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

分配一个对象,对其进行弱引用,超出块范围,并检查 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。块范围似乎不相关。 这是尝试 notDebug 模式。

    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

因为你 运行 我猜是在调试器中。

尝试运行发布版本,然后运行在调试器之外手动运行它。

您希望 GC 是 100% 确定性的,但事实并非如此。

可能发生的一些事情:

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

在GC.Collect后添加:

GC.WaitForPendingFinalizers(); 

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