5

如何定义在类终结期间存储“this”的代码?垃圾收集器应该如何表现(如果在某处定义)?

在我看来,GC 应该多次终结类实例,下面的测试应用程序将打印“66”,但终结器只执行一次,导致应用程序打印“6”。

几行代码:

using System;

namespace Test
{
    class Finalized
    {
        ~Finalized()
        {
            Program.mFinalized = this;
        }

        public int X = 5;
    }

    class Program
    {
        public static Finalized mFinalized = null;

        static void Main(string[] args)
        {
            Finalized asd = new Finalized();
            asd.X = 6;
            asd = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);

            mFinalized = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);
        }
    }
}

我要做的是了解终结器如何管理实例内存。在我的应用程序中,可能希望再次重用实例引用以进行进一步处理。

很明显,终结器不会“释放”内存(至少在我的测试应用程序中)。内存块可以用于其他目的吗?甚至被释放?如果不是,那将是内存泄漏还是什么?

现在,我比以前更困惑了。

4

4 回答 4

8

这是由于复活。通过在终结期间将对象存储在另一个变量中(分配this给一个变量),就 GC 而言,您可以复活对象实例。您可以在 .NET 中复活您的对象,并且您实际上可以使 GC 多次完成对象,但您必须通过GC.ReRegisterForFinalize显式请求它。

有关详细信息,请参阅Microsoft .NET Framework 中的自动内存管理

于 2012-08-16T23:32:25.290 回答
4

GC.Collect 进行扫描,使用终结器对任何对象进行特殊封装,而不是收集它们。一旦这些终结器对象完成,GC 就会再次在这些对象上运行。如果他们不再有资格收集(通过重新生根,就像你一样),那就这样吧。通常终结器只运行一次,但是 IIRC,您可以请求它再次运行。

于 2012-08-16T23:34:45.697 回答
0

我对复活物体的任何良好用途感兴趣。

MSDN 声明“复活很少有好的用途,如果可能的话,你真的应该避免它”。Bill Wagner 在他的 Effective C# 中也说过“你不能让这种构造可靠地工作。不要尝试”。但是这本书已经有 2 年历史了,所以也许有些改变了?

于 2012-08-16T23:32:12.640 回答
0

终结器只被调用一次。您可以自由地将 self 分配给某个地方,并防止对象被垃圾收集。但是一旦对象再次可用于 GC,它就不会运行终结器。

于 2012-08-16T23:33:56.853 回答