为什么继承System.ComponentModel.Component会阻止对象被垃圾回收(根本)

时间:2013-09-03 07:27:50

标签: c# garbage-collection

我最初的问题是,在从例如继承的类中取消注册自引用的事件处理程序是否很重要。零件。他们提供一个Disposed活动,曾经可以去掉一些东西。

但我正在玩它并意识到一些奇怪的事情:从System.ComponentModel.Component派生确实会阻止析构函数被调用(即使在应用程序结束时也是如此。

这是一个显式使用GC.Collect强制收集的示例(仅测试,从不在prod代码中使用此方法)

using System;
using System.ComponentModel;

namespace CSharpEventHandlerLifetime
{
    public class LongLiving : Component
    {

        public LongLiving()
        {
            Console.WriteLine("Creating object");
            // Disposed += (sender, args) => Console.WriteLine("Disposed");
        }

        ~LongLiving()
        {
            Console.WriteLine("Destructor called");
        }

    }

    class Program
    {
        public static void _create()
        {
            using (var l = new LongLiving())
            {
                Console.WriteLine("Generation is {0}", GC.GetGeneration(l));
            }
        }

        static void Main(string[] args)
        {
            _create();

            GC.Collect(); // this should call dtor of LongLiving


            Console.ReadKey(); // wait before end
        }
    }
}

当我完全删除继承的Component类(将using更改为plain new)或将其替换为IDisposable(并实现一些空的Dispose方法)时,我清楚地看到调用GC.Collect调用LongLiving的人。

我不理解这种行为,因为我至少期望在应用程序退出时进入~dtor但是从Component派生时它永远不会发生。

1 个答案:

答案 0 :(得分:8)

Component已经实现了Disposable模式,其中包括完成后对GC.SuppressFinalize的调用。 Dispose块退出时会调用using

因此,对象被垃圾收集,它永远不会被称为终结器。

如果您要进行任何清理,则应覆盖Dispose(bool)

E.g。这是Component s Dispose方法:

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}