IDisposable.Disposeメソッドによってリソースが破棄された場合、以降は破棄されたリソースにアクセスできないようにする必要があります。 このような場合にスローする例外がObjectDisposedExceptionです。 メソッド呼び出しやメンバ参照によって解放済みのリソースへのアクセスが生じる場合にこの例外をスローします。

ObjectDisposedExceptionコンストラクタの引数objectNameには例外をスローしたオブジェクトの名前を指定します。 通常はオブジェクトの名前として型の名前、具体的にはGetType().FullNameを指定します。

以下の例は、解放済みのリソースにアクセスしようとした場合にObjectDisposedExceptionをスローするようにしたものです。

すでに解放済みのリソースへのアクセスを試行した場合にObjectDisposedExceptionをスローする
using System;
using System.Runtime.InteropServices;

class UnmanagedMemory : IDisposable {
  private IntPtr ptr; // アンマネージメモリ領域を参照するポインタ

  public UnmanagedMemory(int size)
  {
    ptr = Marshal.AllocHGlobal(size);
  }

  public void Clear()
  {
    // Ptrが0の場合(すでにDisposeメソッドで解放済みの場合)、例外ObjectDisposedExceptionをスローする
    if (ptr == IntPtr.Zero)
      throw new ObjectDisposedException(GetType().FullName); // 例外の原因となるオブジェクト名として型名を指定する

    // そうでない場合はメソッドの通常の処理を行う
  }

  public void Dispose()
  {
    if (ptr == IntPtr.Zero)
      return; // すでに解放されている場合は何もしない(DisposeメソッドはObjectDisposedExceptionをスローしてはならない)

    Marshal.FreeHGlobal(ptr);

    // 解放済みであることを示すためにIntPtr.Zeroを設定する
    ptr = IntPtr.Zero;
  }
}

class Sample {
  static void Main()
  {
    // IDisposableインターフェイスを実装するオブジェクトを作成する
    // (本来ならusingステートメントを使ったほうがよいが、例示のため省略)
    var mem = new UnmanagedMemory(4);

    // Disposeメソッドを呼び出し、アンマネージリソースを解放する
    mem.Dispose();

    // アンマネージリソースへのアクセスを試みる
    // (オブジェクトはすでに破棄されているため、ObjectDisposedExceptionとなる)
    mem.Clear();
  }
}
実行結果
ハンドルされていない例外: System.ObjectDisposedException: 破棄されたオブジェクトにアクセスできません。
オブジェクト名 'UnmanagedMemory' です。

上記の例にもあるように、IDisposable.Disposeメソッドでは、すでに解放済みの場合であってもObjectDisposedExceptionをスローしないようにします。 ObjectDisposedExceptionは、使用しようとしたリソースが既に解放済みだった場合にスローします。

仮にDisposeメソッドでオブジェクトが破棄されている場合でも、解放済みリソースへのアクセスが生じない処理の場合はObjectDisposedExceptionをスローしないようにすることもできます。 例えば、IsDisposedIsClosedのようなプロパティを用意する場合は、破棄されていてもObjectDisposedExceptionをスローしない動作とします。

MENTAにてテキストチャットによるサポートを行っています。 問題の解決法をお探しの方や.NET/C#を学習中の方はどうぞご利用ください。