web-dev-qa-db-ja.com

IDisposable.Dispose()は自動的に呼び出されますか?

可能性のある複製:
ガベージコレクターはIDisposable.Disposeを呼び出しますか?

管理されていないリソースを持つクラスがあります。私のクラスはIDisposableインターフェイスを実装し、Dispose()メソッドでアンマネージリソースを解放します。 Dispose()メソッドを呼び出す必要がありますか、それとも何らかの方法で自動的に呼び出されますか?ガベージコレクターはそれを呼び出しますか?

53
Padeep

Dispose()は自動的に呼び出されません。 finalizerがある場合、自動的に呼び出されます。 IDisposableを実装すると、クラスのユーザーがガベージコレクターを待つのではなく、リソースを早期に解放できます。

クライアントにとって望ましい方法は、例外がある場合でもDispose()の自動呼び出しを処理するusingステートメントを使用することです。

IDisposableの適切な実装は次のとおりです。

_class MyClass : IDisposable
{
  private bool disposed = false;

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

  protected virtual void Dispose(bool disposing)
  {
    if(!disposed)
    {
      if(disposing)
      {
        // Manual release of managed resources.
      }
      // Release unmanaged resources.
      disposed = true;
    }
  }

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

クラスのユーザーがDispose()を呼び出すと、クリーンアップが直接行われます。オブジェクトがガベージコレクターによってキャッチされると、Dispose(false)を呼び出してクリーンアップを実行します。ファイナライザー(_~MyClass_メソッド)から呼び出された場合、マネージ参照は無効になる可能性があるため、アンマネージリソースのみを解放できることに注意してください。

64
Anders Abel

usingステートメントでオブジェクトをインスタンス化すると、コードがusingブロックを終了するときにDispose()が呼び出されます

using(var myObject = new MyDisposableObject())
{
  blah();
} // Dispose() is called here (or whenever the code exits the block)

usingを使用しない場合、Dispose()を明示的に呼び出してオブジェクトを破棄するのは(呼び出し元のコード)次第です。

また、あなた(MyObjectの実装者)は、呼び出し元がDispose()を呼び出さない場合に備えて、ファイナライザーのサポートを追加できます。詳細 こちら

8
Serge Wautier

リソースを正しく破棄するには、IDisposableを実装し、デストラクタ(ファイナライザ)でDisposeを呼び出す必要があります。

class Foo : IDisposable
{
    private bool m_disposed = false;

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

    ~Foo()
    {
        Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
        if (!m_disposed)
        {
            if (disposing)
            { 
                //release managed resources
            }
            //release unmanaged resources

            m_disposed = true;
        }
    }
}
7
Cheng Chen

willこのメソッドを手動で呼び出す必要があります。

using(var myclass = new MyClass())
{
   // do something with myclass
}

// now 'myclass'is Disposed
4
Hans Kesting