IDisposableとFinalizeのはざまで
タイトルはともかく。
.netでIDisposableを実装したとき、Finalizeはどーすりゃええん? という話だが。
IDisposable実装の作法も含めてこういう話。
- アンマネージリソースを(直接、間接に)扱ってれば、IDisposableは実装しとく。
- アンマネージリソースを扱うことがないのなら、IDisposableは実装しちゃダメ(人間が見てDisposeせんならんと思ってしまう)
- IDisposableを書くときは、必ず引数なしとboolean引数ありの二つをどっちもオーバライド。(下記参照)
- IDisposableを実装したらFinalizeも必ず書く。(Dispose()の呼び忘れを、ランタイムに拾わせるように)
- と、上記のお約束の上で、
- 引数なしDispose()では、Dispose(true)を呼んで、GC.SuppressFinalize(this)。
- Finalize()では、Dispose(false)を呼ぶ。何か継承してたらその後でbase.Finalize()。
- 引数ありのDispose(boolean)で、リソースのクリーンアップを実装する。
(引数trueのときだけマネージリソース(あれば)のクリーンアップをするように。
さらにマネージリソースは複数回クリーンアップしないように仕込み入れておく。)
そしてアンマネージリソースは引数に関わらずクリーンアップし(ただし複数回はしないように)、
最後にbase.Dispose(boolean)を呼ぶ。
(this.Dispose()が例外吐くかもなら、try-catch-finally仕掛けてfinallyできっちりbase.Dispose(boolean)を呼ぶように。)
おおよそのところは
(MSDN)アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装
(MSDN)CLR 徹底解剖: IDisposable について
また、他に
IDisposable を実装している型からの継承:Gushwell's Dev Notes
とか。