1

可能重复:
正确使用 IDisposable 接口

我试图从书籍、互联网和 stackoverflow 上找到我的问题的实际答案,但到目前为止没有任何帮助我,所以希望我能准确地表达我的问题以使其有意义。

一般来说,我总是发现如何释放内存的基本用法相同,大约是。如下,我确实理解代码本身:

public class MyClass : IDisposable
{
    bool disposed = false;
    public void Dispose()
    {
        if (!disposed)
        {
        Dispose(true);
        GC.SuppressFinalize(this);
        disposed = true;
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
        //free managed ressources
        }
    // free other ressources
    }

    ~MyClass()
    {
        Dispose(false);
    }
}

方法的工作方式完全有意义。但现在我的问题是:为什么我们需要基类 IDisposable?在此代码示例中,我们定义了一个名为Dispose(). 正如我在各处读到的那样,该方法是 IDisposable 的一部分,但是我们刚刚在其中定义了该方法MyClass,如果我们不实现基类 IDisposable,此代码仍然可以工作,还是我对这个假设有误?

我对 C# 并不完全陌生,但我还有很多东西要学,所以希望有人能在这里带领我朝着正确的方向前进。我检查了另一个具有相同问题的帖子,但找不到它,所以如果它确实存在并且它确实回答了我的问题,请带我去那里,我将删除这个帖子。

4

4 回答 4

9

你是对的,作为你的析构函数~MyClass调用Dispose,似乎不需要 interface IDisposable

Dispose不仅仅由析构函数调用。当您想要处置非托管资源时,您可以在代码中自己调用它。它是必需的,因为您不知道何时调用析构函数(这取决于垃圾收集器)。

最后,IDisposable.Dispose在您使用using.

using(MyDisposableClass myObject = new MyDisposableClass())
{
    // My Code
}

相当于:

MyDisposableClass myObject = new MyDisposableClass();
try
{
    // My Code
}
finally
{
    myObject.Dispose();
}
于 2013-01-28T01:26:35.287 回答
2

IDisposable.Dispose 的实际实现调用 Dispose(bool) 的基类实现。从这个类继承的任何人现在都需要处理以下任务:

public override Dispose(bool disposing)
{
    base.Dispose(disposing);
    //my disposal code
}

使用这种公认的模式允许继承者扩展处置代码,而不会破坏基类的处置。

通常,如果您没有可处置的非托管资源并且有能力密封您的课程,您可以使用以下代码简化问题:

public sealed class SomeDisposable:IDisposable
{
    public void Dispose()
    {
       //just go ahead and clean up
       //because we're sealed, no-one can ever break
       //this code via inheritance
    }
    //~SomeDisposable()
    //{
    //   if this is being called then it will be called
    //   on all referenced and unrooted IDisposables too
    //   If everything is managed, that means we've got nothing
    //   left to clean up, so we can omit this Finalizer 
    //}
}
于 2013-01-28T01:24:56.557 回答
2

实施 IDispose 为您提供了一个地方来释放您“持有”的资源,例如流、句柄或数据库连接。

从垃圾收集器调用 Dispose(),基本上是询问对象:“如果有什么你不再需要,但我想不通;现在释放它;清理!”

在某种意义上类似于 C++ 中的析构函数

不同之处在于 C++ 析构函数会立即被调用,而 Dispose() 会及时被调用。

在大多数情况下,您不需要实现它。GC 足够聪明,可以在 90% 的情况下找出如何释放已用资源。

但是例如:释放流使用的内存不会自动关闭流,释放数据库连接也不会关闭它。

实现 Dispose 允许您在释放对象时关闭文件:

internal class Something : IDisposable {
private Stream stream;

public void SomeMethod() {
    stream.Write("nskdns");
}

public void Dispose() {
    if (stream != null) {
        stream.Close();
    }
}

此外:实现 IDispose 使您有机会在 using 语句中使用该类:

public void Example() {
    using (var x = new Something())
    {
        x.SomeMethod();
    }
}

确保 x 在被 GC 释放时总是会关闭已使用的流。

但是,我更喜欢类上的专用 Close() 方法,以允许显式关闭流,而不是依赖 GC 并调用 Dispose()

于 2013-01-28T01:50:42.360 回答
1

它与usingC# 编译器的块一起使用。

于 2013-01-28T01:24:05.637 回答