単にリソースを明示的に解放できるようにしたいならば、IDisposableインターフェイスを使わずともRelease
やClose
といった解放用のメソッドを用意しておき、それらのメソッドを呼び出すようにすることもできます。 しかし、IDisposableを実装しておくと、usingステートメントによる構文の補助に基づく確実な解放処理が行えるようになります。 加えて、IDisposableインターフェイスによって、型が解放されるべきリソースを保持していることを表明できます。
Dispose
以外のメソッド名で解放処理を提供したいといった場合には、次の例のように別名の解放用メソッドを公開しつつ、IDisposable.Disposeメソッドは明示的に実装(またはPrivate
として実装)し、それを呼び出すようにすることができます。 このようにすることでDispose
以外のメソッド名で解放処理を提供できると同時に、IDisposableインターフェイスによる解放処理も提供できます。
IDisposableインターフェイスを実装し、Dispose以外のメソッド名で解放処理を公開する
using System;
using System.Runtime.InteropServices;
class UnmanagedMemory : IDisposable {
public IntPtr Ptr; // アンマネージメモリ領域を参照するポインタ
public UnmanagedMemory(int size)
{
// メモリ領域を確保する
Ptr = Marshal.AllocHGlobal(size);
}
// メモリ領域を確保するためのメソッドとして、Disposeではない別名のメソッドを提供する
// (IDisposable.Disposeを明示的な実装にし、それを呼び出すようにする)
public void Free() => (this as IDisposable).Dispose();
// '明示的な'IDisposable.Disposeの実装
void IDisposable.Dispose()
{
if (Ptr == IntPtr.Zero)
return;
Marshal.FreeHGlobal(Ptr);
Ptr = IntPtr.Zero;
}
}
class Sample {
static void Main()
{
// IDisposableインターフェイスを実装するオブジェクトを作成する
// (本来ならusingステートメントを使ったほうがよいが、例示のため省略)
var mem = new UnmanagedMemory(4);
Marshal.WriteInt32(mem.Ptr, 16);
// Freeメソッドでアンマネージリソースを解放する
// (このメソッド経由でIDisposable.Disposeメソッドが呼び出される)
mem.Free();
}
}