あなたは要点を逃しています。クラスが を実装するときはいつでもIDisposable
、使い終わったら呼び出す必要がありDispose
ます。
クラスがアンマネージ リソースを使用するかどうかは、クラスの内部的なものであるため、まったく気にする必要はありません。アンマネージ リソースを使用するすべてのクラスには、クラスを明示的に破棄しなかった場合にそれらのアンマネージ リソースをクリアするファイナライザーも必要です。Dispose
より決定論的かつ即時の方法で、そのリソースをクリーンアップできるようにするだけです (マネージドとアンマネージドの両方。ただし、これは必ずしもメモリをすぐに解放することを意味するわけではありません)。たとえば、Dispose
aFileStream
を実行するとファイル ハンドルがすぐに解放されますが、実行しない場合Dispose
(またはClose
)、ファイルは次の収集とファイナライズまで開かれます。
編集:
Dispose
管理対象リソースをクリーンアップするためにも必要である可能性があることを示すために、イベント ハンドラーのみを確認する必要があります。特に、自分よりも寿命が長いクラスのイベントを購読している場合:
var control = new MyHelperControl();
MyParentForm.Click += control.DoSomething();
これで、スコープ外になったとしても、イベント ハンドラーによって参照されているcontrol
限り存続します。MyParentForm
親の寿命がアプリケーション全体と同じである場合、同じ問題がばかげた比率に発展します。これは、巨大なメモリ リークになる可能性があります。例としては、アプリケーションのメイン フォームまたは静的イベントにイベント ハンドラーを登録することがあります。
で起こる他のこともあるかもしれませんDispose
。たとえば、再び Windows フォームで を呼び出すDispose
と、Control
さまざまなことが起こります。
- アンマネージ リソースはすべて解放されます。Winforms コントロールはある程度ネイティブ コントロールのラッパーであるため、これは通常、多くのリソース (コントロール自体、ペン、ブラシ、画像など) です。これらはすべてネイティブ リソースです。それらはすべてファイナライザーを持っているため、 a を忘れた場合にも解放されますが
Dispose
、より多くの時間がかかる可能性があります。これは、これらのオブジェクトを多数作成および破棄する場合に特に苦痛です。たとえば、GDI+ オブジェクト ハンドルの供給には限りがあり、使い切れば手に負えなくOutOfMemoryException
なります。
- すべてのサブコントロールを破棄します。
- コンテキスト メニュー ハンドラーをすべて削除します (コンテキスト メニューは、別のコントロールにのみリンクされている別のコンポーネントであることを思い出してください)。
- データ バインディングをすべて削除します。
- 親コンテナがあれば、そこから自身を削除します。
- コントロールが独自のメッセージ ループを持つウィンドウである場合は、メッセージ ループを強制終了します。
面白いのは、管理されていないリソースが最も重要でないということです。実際には、常にファイナライザーがあります。ファイナライザーで管理された参照を処理することは多かれ少なかれ禁止されているため、管理されたリソースはよりトリッキーです (既に解放されているか、解放されている最中であるか、途中で解放され始める可能性があるため)ファイナライザーの...複雑です)。そのため、ファイナライザーでこれを行うMyParentForm.Click -= this.OnClick;
のは良いことではありません。言うまでもなく、そのようなすべてのクラスをファイナライズ可能にする必要があります。これは、特にファイナライザーが実際に実行されることを期待する場合( Dispose
. GC は、このインスタンスがファイナライズを必要としなくなったことを警告されます)。