在最终确定时存储'this'

时间:2012-08-16 23:28:21

标签: c# garbage-collection .net-2.0 finalizer

如何定义在课程定稿期间存储'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 个答案:

答案 0 :(得分:8)

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

有关详细信息,请参阅Automatic Memory Management in the Microsoft .NET Framework

答案 1 :(得分:4)

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

答案 2 :(得分:0)

我对复活对象的任何好用都很感兴趣。

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

答案 3 :(得分:0)

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