以下は、disposeパターンにしたがって、IDisposableインターフェイスとファイナライザを実装するクラスResource
を作成する例です。 このクラスでは継承を許可しないものとします。
disposeパターンに従った継承を許可しないクラスの実装例
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
' 使用後に解放されるべきリソースを扱うクラス
NotInheritable Class Resource
Implements IDisposable
Private disposed As Boolean = False ' リソースが破棄(解放)されていることを表すフラグ
Private ptr As IntPtr = Marshal.AllocHGlobal(4) ' コンストラクタ等で確保されるアンマネージリソースを想定したオブジェクト
Private stream As Stream = Stream.Null ' コンストラクタ等で確保されるマネージリソースを想定したオブジェクト
' ファイナライザ
Protected Overrides Sub Finalize()
' アンマネージリソースのみを破棄させる
Dispose(false)
End Sub
' IDisposable.Disposeの実装
Public Overloads Sub Dispose() Implements IDisposable.Dispose
' アンマネージリソースと、マネージリソースの両方を破棄させる
Dispose(true)
' すべてのリソースが破棄されているため、以後ファイナライザの実行は不要であることをガベージコレクタに通知する
GC.SuppressFinalize(Me)
End Sub
' リソースの解放処理を行うためのメソッド
Private Overloads Sub Dispose(ByVal disposing As Boolean)
' 既にリソースが破棄されている場合は何もしない
If disposed Then Return
' アンマネージリソースと、マネージリソースの両方の破棄が要求された場合
If disposing Then
' 破棄されていないマネージリソースの解放処理を行う
If Not stream Is Nothing Then
stream.Close() ' Disposeメソッド、あるいはそれを呼び出すメソッドを呼び出して解放する
stream = Nothing
End If
End If
' 破棄されていないアンマネージリソースの解放処理を行う
If ptr <> IntPtr.Zero Then
Marshal.FreeHGlobal(ptr)
ptr = IntPtr.Zero
End If
' リソースは破棄されている
disposed = True
End Sub
' 既にリソースが破棄されているかチェックして、ObjectDisposedExceptionをスローするためのメソッド
Private Sub ThrowIfDisposed()
If disposed Then Throw New ObjectDisposedException(Me.GetType().FullName)
End Sub
' 保持しているリソースを使って何らかの操作を行うメソッドを想定
Public Sub UseResource()
' 既にリソースが破棄されているかチェックし、破棄されていればObjectDisposedExceptionをスローする
ThrowIfDisposed()
' 以降、リソースが利用可能な場合はそれを使った操作を行う
End Sub
End Class
ここでは例示のためハンドル・ポインタをそのまま扱っていますが、可能ならSafeHandleでラップするようにします。 このほか、個々の事項については以下を参照してください。