我们甚至需要在.NET中使用Finalizer方法吗?

时间:2012-11-28 17:15:28

标签: c# winforms memory idisposable

我的类正在使用COM资源,我从IDisposable继承了它。并且为了清理非托管资源,我有Dispose()方法,我在调用Marshall.ReleaseCOMObject()方法...所以我的问题是我们还需要一个Destructor方法(Finalizer)吗?发布COM资源?当我有finalzier方法并在其中调用Marshal或Dispose时,我将得到RCW错误,当我删除终结器方法时,我将不再得到RCW错误但是如果我查看内存分析器,我可以看到非托管资源内存不断增加eveery时间我打开有这个COM资源的表单...所以看起来喜欢它没有清理它?那么在C#应用程序中清理COM资源的正确方法是什么?

我将使用我即将推出的一些代码示例更新问题。

感谢。

private MyCOMobject theCOMobject = null;

static SuppressFieldCntrlr()
{
    new SomeCalss();
}


private bool disposed = false;

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

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
           //nothing in here, is it just for Managed Resources? 
        }

        Marshal.ReleaseComObject(this);
        MethodFoo(false);

        disposed = true;
    }
}

3 个答案:

答案 0 :(得分:2)

如果您的类没有直接拥有非托管资源,并且您知道任何派生类都不会直接拥有非托管资源(例如,因为您的类是密封的,您的类是内部的),那么您不需要终结。

就个人而言,即使不是绝对必要,我也会用终结器实现标准模式。主要是出于最小惊喜的原则,并且因为其他人可能决定在将来解封它或允许派生类使用非托管资源。

另请注意,COM对象是托管资源,因此在disposing为true时应调用ReleaseComObject:

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
            // Dispose managed resources
            Marshal.ReleaseComObject(this);
        }
        // If you directly own unmanaged resources, they'd be freed here

        disposed = true;
    }
}

答案 1 :(得分:2)

您正在封装托管对象,而不是非托管对象。你没有P / invoke'd来获取Win32文件句柄,或设备上下文,或类似的东西;相反,您已获得对托管对象的引用 - RCW。您应该在Marshal.ReleaseComObject方法的if (disposing)部分中致电Dispose(bool)

RCW本身将有一个终结器,它将负责实际COM对象的IUnknown->Release()簿记,因此如果您尚未在需要进行终结时调用ReleaseComObject,垃圾收集器将删除COM对象。

答案 2 :(得分:0)

如果我们有非托管资源,强烈建议使用终结器。 在这种情况下:

~ClassName
{
    Dispose(false);
}