問題タブ [idisposable]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
inversion-of-control - ServiceContainer、IoC、および使い捨てオブジェクト
質問があります。この主観的なものにタグを付けるつもりです. 良いアイデアや示唆に富んだものを期待しています。長々とした質問で申し訳ありませんが、文脈を知る必要があります。
質問は基本的に次のとおりです。
- IoC コンテナーに関連して具象型をどのように処理しますか? 具体的には、それらを破棄する必要がある場合、誰がそれらを破棄する責任がありますか? また、その知識は呼び出し元のコードにどのように伝達されますか?
それらを IDisposable にする必要がありますか? そうでない場合、そのコードは将来性がありますか、それとも使い捨てオブジェクトを使用できないという規則ですか? インターフェイスと具象型に IDisposable-requirements を適用して将来的に保証する場合、コンストラクター呼び出しの一部として挿入されるオブジェクトは誰の責任ですか?
編集: @Chris Ballardの回答を受け入れました。これは、最終的なアプローチに最も近いものだからです。
基本的に、常に次のような型を返します。
次に、このインターフェイスを実装するオブジェクトを .Resolve と .TryResolve の両方から返すので、呼び出しコードで取得するものは常に同じ型になります。
現在、このインターフェイスを実装するオブジェクトIService<T>は IDisposable であり、常に破棄する必要があります。IService<T>サービスを解決してオブジェクトを破棄するかどうかを決定するのは、プログラマの責任ではありません。
ただし、これは重要な部分であり、サービス インスタンスを破棄する必要があるかどうかに関係なく、その知識は を実装するオブジェクトに組み込まれているIService<T>ため、ファクトリ スコープのサービスである場合 (つまり、Resolve への各呼び出しは新しいサービス インスタンスで終了します) )、IService<T>オブジェクトが破棄されるときにサービス インスタンスが破棄されます。
これにより、プーリングなどの他の特別なスコープをサポートすることも可能になりました。これで、最小で 2 つのサービス インスタンス、最大で 15、通常は 5 が必要であると言えます。これは、.Resolve を呼び出すたびに、使用可能なオブジェクトのプールからサービス インスタンスを取得するか、新しいインスタンスを構築することを意味します。その後、IService<T>プールされたサービスを保持するオブジェクトが破棄されると、サービス インスタンスはそのプールに解放されます。
確かに、これによりすべてのコードは次のようになります。
しかし、これはクリーンなアプローチであり、使用中のサービスや具体的なオブジェクトのタイプに関係なく同じ構文を使用するため、受け入れ可能なソリューションとしてこれを選択しました。
後世のために、元の質問が続きます
長い質問がここに来ます:
使用している IoC コンテナーがあり、最近、何が問題になるかを発見しました。
IoC 以外のコードで、たとえばファイルを使用したい場合、次のようなクラスを使用しました。
ファイルを閉じる必要があることはわかっており、クラス自体が IDisposable を実装していたため、このクラスが限られたリソースを保持するものであったかどうかは疑問の余地がありませんでした。ルールは、IDisposable を実装する、オブジェクトを構築するすべてのクラスを破棄する必要があるという単純なものです。質問はありません。Dispose の呼び出しがオプションかどうかを決定するのは、このクラスのユーザー次第ではありません。
では、IoC コンテナーに向けた最初のステップに進みましょう。コードがファイルと直接やり取りするのではなく、1 つの間接的なレイヤーを通過することを望んでいないと仮定しましょう。この例では、このクラスを BinaryDataProvider と呼びましょう。内部的には、クラスはまだ使い捨てオブジェクトであるストリームを使用しているため、上記のコードは次のように変更されます。
これはあまり変わりません。クラスが IDisposable を実装しているという知識はまだここにあります。質問はありません。Dispose を呼び出す必要があります。
しかし、現時点ではそのような限られたリソースを使用しないデータを提供するクラスがあると仮定しましょう。
上記のコードは、次のように記述できます。
OK、ここまでは順調ですが、ここからが本題です。特定の具象型に依存するのではなく、IoC コンテナーを使用してこのプロバイダーを注入するとします。
コードは次のようになります。
オブジェクトにアクセスできる独立したインターフェースが利用可能であると想定していることに注意してください。
上記の変更により、実際に破棄する必要があるオブジェクトを後で使用したい場合はどうなるでしょうか? そのインターフェイスを解決する既存のコードは、オブジェクトを破棄するように記述されていません。
私たちの見方では、解決策を 1 つ選択する必要があります。
- 登録されている具象型が IDisposable を実装しているかどうかを確認する実行時チェックを実装し、それを介して公開されるインターフェイスも IDisposable を実装する必要があります。これは良い解決策ではありません
- 使用されるインターフェイスに制約が課せられる前に、それらは常に IDisposable から継承する必要があります。
- 具体的な型を IDisposable にできないランタイムを強制します。これは、IoC コンテナーを使用するコードによって具体的に処理されないためです。
- オブジェクトがIDisposableを実装して「正しいことをする」かどうかをチェックするのはプログラマーに任せてください。
- 他にもありますか?
また、コンストラクターにオブジェクトを注入するのはどうですか? 私たちのコンテナ、および調査した他のコンテナのいくつかは、具象型のコンストラクターのパラメーターに新しいオブジェクトを注入することができます。たとえば、インターフェイスBinaryDataProviderを実装するオブジェクトが必要な場合ILogging、これらのオブジェクトに IDispose-"機能" を適用する場合、ロギング オブジェクトを破棄するのは誰の責任でしょうか?
どう思いますか?良くも悪くも意見が欲しいです。
c# - Icon.ToBitmap() を呼び出した後にアイコンを破棄しても安全ですか?
イメージを作成するために呼び出した後System.Drawing.Icon.ToBitmap()、オリジナルを破棄しても安全Iconですか?
.net - キャッシュされた IDisposable オブジェクトを管理する方法は?
作成に費用がかかるオブジェクトがあります。このオブジェクトは、処理が完了したら明示的に解放する必要があるアンマネージ リソースを使用するため、IDisposable() を実装します。作成コストを最小限に抑えるために、これらの高価なリソースのインスタンスのキャッシュが必要ですが、廃棄の処理方法がわかりません。
オブジェクトを使用するメソッドが破棄を担当している場合、破棄されたインスタンスがキャッシュに残り、再作成する必要があり、キャッシュのポイントが無効になります。オブジェクトを使用するメソッドでオブジェクトを破棄しないと、破棄されません。キャッシュから取り出されたときに破棄できると思っていましたが、メソッドによってまだ使用されているインスタンスを破棄してしまう可能性があります。
それらを範囲外にしてガベージコレクターによって収集し、その時点でリソースを解放することは有効ですか? これは間違っていると感じ、それらが使い捨てであるという考えに反しています...
c# - スローしないように IDisposable.Dispose() を実装する必要がありますか?
C++ の同等のメカニズム (デストラクタ) については、通常は例外をスローしないようにすることをお勧めします。これは主に、そうすることでプロセスを終了する可能性があるためです。これは、ごくまれにしか良い戦略ではありません.
.NET での同等のシナリオでは ...
- 最初の例外がスローされます
- 最初の例外の結果として、finally ブロックが実行されます。
- finally ブロックは Dispose() メソッドを呼び出します
- Dispose() メソッドが 2 番目の例外をスローする
... プロセスはすぐには終了しません。ただし、.NET は最初の例外を 2 番目の例外で不用意に置き換えるため、情報が失われます。したがって、コール スタックのどこかにある catch ブロックでは、最初の例外が表示されることはありません。ただし、最初の例外に関心があるのは、通常、最初の例外の方が、問題が発生し始めた理由についてより良い手がかりを提供するためです。
.NET には、例外が保留されている間にコードが実行されているかどうかを検出するメカニズムがないため、IDisposable を実装する方法は実際には 2 つしかないようです。
- Dispose() 内で発生するすべての例外を常に飲み込みます。OutOfMemoryException、ExecutionEngineExceptionなどを飲み込んでしまう可能性があるため、良くありません。通常、別の例外が保留されていない状態で発生した場合、プロセスを破棄させます。
- すべての例外を Dispose() から伝播させます。問題の根本原因に関する情報を失う可能性があるため、良くありません。上記を参照してください。
では、2 つの悪のうち、どちらが小さいのでしょうか? より良い方法はありますか?
編集:明確にするために、私は Dispose() から積極的に例外をスローするかどうかについて話しているのではなく、Dispose() によって呼び出されたメソッドによってスローされた例外を Dispose() から伝播させるかどうかについて話している、たとえば:
c# - C# デストラクタ (別名: ファイナライザ) に関連するコストは?
デストラクタは、オブジェクトが保持しているアンマネージ リソースのみを解放する必要があり、他のオブジェクトを参照するべきではありません。管理参照しかない場合は、デストラクタを実装する必要はありません (実装すべきではありません)。これは、管理されていないリソースを処理する場合にのみ必要です。デストラクタを使用するとコストがかかるため、管理されていない貴重なリソースを消費するメソッドにのみ実装する必要があります。
この記事ではこれについて詳しく説明していませんが、C# でデストラクタを使用すると、どのようなコストが発生するのでしょうか?
注: GC と、信頼できるタイミングでデストラクタが呼び出されないという事実については知っていますが、それ以外に何かありますか?
c# - IDisposable とは何ですか?
.NET にガベージ コレクションがある場合、なぜ明示的に呼び出す必要があるのIDisposableでしょうか。
.net - 未処理の使い捨てオブジェクトの追跡
コードをスキャンし、IDisposable を実装するどのオブジェクトがコンパイル時または実行時にコード ベースで破棄されていないかを判断できるツールはありますか?
コード内にオブジェクトを破棄していない可能性のある領域がありますが、振り返ってどのオブジェクトが最初にこれを必要としているかを確認するのは困難です。