在下列情况下如何确保没有内存泄漏

时间:2010-12-06 08:14:34

标签: c# .net

如果某个类具有包含非托管资源的属性。使用类

时如何确保没有内存泄漏
Class A
{
         B {get; set;}
}

B包含非托管资源。

4 个答案:

答案 0 :(得分:7)

实施IDisposable并通过调用Dispose()来清理您的非托管资源,最好将Dispose的调用放在finally语句中,以便即使在案例中也可以清理资源例外。

C#有一个using关键字,您可以使用它来确保调用Dispose方法,即使抛出异常也是如此。

编辑:根据Ran的答案合并调用GC.SuppressFinalize和终结器实现

class A : IDisposable
{
    private bool _disposed;

    ~A()
    {
        this.Dispose(false);
    }

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

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // dispose managed resources
            }

            // clean up unmanaged resources

            _disposed = true;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (var someInstance = new A())
        {
            // do some things with the class.
            // once the using block completes, Dispose
            // someInstance.Dispose() will automatically
            // be called
        }
    }
}

答案 1 :(得分:4)

使用IDisposable可能还不够,因为它依赖于用户记住调用Dispose或使用using等。

要获得完整的解决方案,请合并IDisposable和终结器。像这样:

编辑:根据 SpeksETC 的评论在Dispose方法中进行了一些更正。

class MyClass : IDisposable
{
    ~MyClass() 
    {
        Dispose(false);
    }

    public void Dispose()
    {
        GC.SupressFinalize();
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposing)
        {
            // clear unmanaged resources here (can only be called once)
            ...
        }

        // dispose called explicitly by the user, clean up managed resources here
        ...
    }
}

这可确保始终清除本机资源,即使用户忘记呼叫Dispose,同时仍允许用户提前清除资源。

if实施中的Dispose是必需的,因为如果要完成此课程,您可能不会在您的成员上致电Dispose,因为他们可能已经过GC。< / p>

答案 2 :(得分:1)

我认为必须指出B是托管资源,只有包含非托管资源。

因此,A应该在其Dispose()方法中实现IDisposable并处理B,但不需要终结器,因为它没有任何非托管资源来清理 - 终结器需要在B本身内实现。即使你实现了终结器,它也会调用一个看起来像这样的Dispose:

protected virtual void Dispose(bool disposing) 
    { 
        if (disposing) 
        { 
            // dispose called explicitly by the user, clean up managed resources here 
            b.Dispose() 
        } 

        // no unmanaged resources to clean up so do nothing which makes Finalizer unneccesary
        ... 
    } 

答案 3 :(得分:0)

SpeksEtc是正确的,如果B包含非托管资源,那么B应该确保没有泄漏而不是A.

但是什么是非托管资源?SafeHandle类有帮助吗?然后B将包含一个SafeHandle,它将包含非托管资源,您不必担心它。

相关问题