3

.NET フレームワークを使い始めたばかりです。IDisposable今日はインターフェースとメソッドを教わりましたdispose()。私はそれに関していくつかのことを教えられました:

dispose()オブジェクトに対応するクリーンアップ コードを含める必要があります (ファイルやデータベース接続など、オブジェクトによって占有されているリソースを閉じるなど)。

メソッドで実行しない場合はdispose()、デストラクタで同じことを実行できますが、すぐに実行できるわけではなく、GC のなすがままに任せられるとも言われました。

また、クリーンアップ コードをまったく提供しない場合、GC は、オブジェクトが保持していたリソースへのすべての接続を強制的に終了します。したがって、クリーンアップ コードを自分で処理する必要があります。

しかし、CLR がこれを単独で処理しないのはなぜでしょうか? メモリ管理を処理し、ガベージ コレクションを処理します。したがって、どのオブジェクトがどのリソースを保持しているか、およびそのオブジェクトがいつ消滅するかをよく知っている必要があります。では、それらのリソースの割り当ても解除できるはずですか?

何人かに聞いてみました。私が与えられた答えは、GC が強制的に閉じるのに対し、適切に閉じる必要があるためであるというものでした。それは実際に理由ですか?

4

8 に答える 8

3

.NET には、GC が認識できるマネージ コード以外の多くの機能があります。すべてのファイル ハンドル、データベース接続、ネットワーク ソケットなど、膨大な量のアンマネージ コードが関係しています。かなりの C# アプリケーションから呼び出しているほぼすべての BCL 関数で、C++ で記述され (そして神が VB6 を禁止するかもしれません)、OS の内部に深く埋め込まれている大量のアンマネージ関数のようにヒットすることになるとは信じられません。自体。これらの関数はすべて、管理されていないメモリ、ハンドルなどを割り当てています...管理された世界はそこで何が起こるかを知りません。

たとえば、ファイル ( FileStream) を開くたびに、基本的に (もちろん舞台裏で) CreateFileアンマネージ Win32 関数を呼び出しています。この関数は、管理されていないファイル ハンドルをファイル システムから直接割り当てます。.NET と GC には、このアンマネージ コードとそれが行うすべてのことを追跡する方法がまったくありません。そのため、これらのクラスは IDisposable インターフェイスを実装しています。そのため、インスタンスを常にusing ステートメントでラップし、例外が発生した場合でも Dispose メソッドが常に呼び出されるようにし、これをできるだけ早く行うことができます。Dispose メソッドは、別のアンマネージ関数を呼び出して、作成した混乱を解消します。

したがって、基本的に IDisposable インターフェイスについて考える方法は次のとおりです。

完全に管理された言語 (たとえば Microsoft Research のMidoriなど) で記述されたオペレーティング システムがある日は、IDisposable はおそらく不要になるでしょう。GC は、発生するすべての情報を持っているため、IDisposable を完全に置き換えることができるからです。このシステム内。

于 2012-07-27T15:07:05.080 に答える
2

とのポイントはIDisposableアンマネージメモリDispose()をクリーンアップする必要があるということです。これは.NETが割り当てなかったメモリであり、外部ソースからのものであるため、GCはそれを知ることができません。したがって、自動的にクリーンアップすることはできません。本質的に、それはまさに管理されたメモリと管理されていないメモリの違いです;-)

一般にDispose()、クラスが使用するアンマネージ リソースをクリーンアップするために実装し、呼び出すファイナライザーも実装する必要がありDispose()ます。ただし、ファイナライザーは単なる保護手段です。呼び出し元がクラスを適切に破棄するのを忘れた場合、これらのリソースが最終的にクリーンアップされるようにします。

于 2012-07-27T15:07:28.563 に答える
1

インターフェースは、管理されていないリソースIDisposableをクリーンアップする方法を提供するためにあります。CLR は、マネージドリソースのみを管理します。

言い換えれば、CLR は、管理するものをクリーンアップする方法しか知りません。システムの残りの部分への接続を開く場合 (ファイルを開く、データベース接続など)、それらはユーザーの責任であり、それらをクリーンアップする方法を CLR に指示する必要があります。

于 2012-07-27T15:06:36.603 に答える
1

このインターフェイスは、マネージド リソースとアンマネージド リソースを決定論IDisposable的に破棄できるようにするための単なる規則です。それだけでは、ガベージ コレクションを置き換えたり、ガベージ コレクタ自体に関連することを行ったりすることはありません。

アンマネージ リソースの場合は、(ファイナライザーまたは決定論的破棄で) 処理されない限り、プロセスが終了するまでメモリ リークとして残るため、より明白です。マネージド メモリでは、アイテムを決定論的に破棄しない場合、アイテムは管理されているため、GC によって非決定論的に収集されます (コレクションの最終的な適格性を想定) (これは、破棄パターンにマネージド アイテムが含まれない理由でもあります)ファイナライザールートで)。

IDisposableそれ自体は何もしません。それは、using消費可能なリソース、管理されていないメモリ、外部アイテムなどを使用するアイテムを処理するときに人々が見つけることを期待する、認識されたインターフェイス (およびキーワードを使用してコードでサポートされている) にすぎません。

CLR は、外部アイテムがいつ終了したかを認識できない可能性があります。これは、アプリケーションのフローに完全に依存しています。オブジェクトを破棄するタイミングもわからない場合は、ファイナライザーの構文が役立ちます。カスタム クラスにファイナライザーを実装すると、ガベージ コレクション プロセスは、最終コレクションの直前にこのファイナライザーを実行します。身だしなみを整える最後のチャンスです。

于 2012-07-27T15:07:44.367 に答える
1

.NET オブジェクトのメモリ管理のみを処理できます。アンマネージ リソースを使用する必要があるコード (たとえば、C++ ライブラリと対話するため) は、ガベージ コレクターの規制の対象外になります。そのすべてのコードは、いつリソースを解放するかを昔ながらの方法で伝える必要があります。

于 2012-07-27T15:07:52.270 に答える
1

.Net フレームワーク (および GC) が管理されていないリソースを解放する方法を知る方法はありません。できることは、マネージ コードがリソースに対して持っている参照を破棄することだけです。データベースサーバーへの接続で実際に .Close() を呼び出す方がはるかに優れています (それにより、接続が利用可能な接続のポーリングに戻る必要があることを伝えます)。設定された秒数の後。

そのため、管理されていないリソースを参照するときは、可能な限り IDisposable インターフェイスを使用してください。

于 2012-07-27T15:10:54.517 に答える
1

IDisposable特定のアーティファクトを GC で処理したくない場合に使用します。最も一般的な例は、接続またはファイル ハンドルです。ファイルを解放する前に GC が実行されるのを待ったり、データベースへの接続を閉じたりするのを待ちたくありません。それがいつ起こるかわからないからです。

ほとんどの人IDisposableはアンマネージ リソースを関連付けますが、これはほぼ正確ですが、ファイナライザーがそれらを処理する適切な .NET の方法であることを忘れています。IDisposableプログラムにとって重要な場合、決定論的に破棄する方法を提供します。

于 2012-07-27T15:11:05.003 に答える
0

GC はこの管理されていないリソースに関する情報を持っていないため、管理されていないリソースをファイル アクセスまたは接続データベースとして破棄するために Dispose を使用します。

Finalize を使用することもできますが、リソースをファイナライズ構造に保存し、このファイナライズ構造によって廃棄サイクルの最後に GC パスを保存するため、パフォーマンスが高くありません。

于 2012-07-27T15:10:37.423 に答える