none
アンマネージリソース と Dispose と GC の関係について RRS feed

  • 質問

  • GC と Dispose とアンマネージリソースの関係に関して質問です。

    先日、以下のスレッドにおいて回答したところ、多くの方に指摘頂き疑問に思ったのですが、

    PictureBoxの内容をClipboardへコピーするには

    .NET Framework で提供されている標準的なクラスにおいては


    1.アンマネージリソースを扱うクラスは IDisposable インターフェイスを継承し、Dispose メソッドを実装している。

    2.仮に Dispose が実行されなかった場合でも、Finalize メソッド内で Dispose をコールするよう設計されている。

    3.よって、ほとんどのアンマネージリソースは、アプリケーション終了時に GC によって安全に解放される筈である。


    と理解してもいいのでしょうか?

    また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。

    2009年11月16日 4:12
    モデレータ

回答

  • 1 は、「マネージドなメモリ以外のリソースを扱うクラス」とすべきでしょう。マネージリソース(要するに IDisposable を実装するメンバ)を持つクラスも一般的に IDisposable を実装するのが普通です(StreamWriter など)。
    ちなみに、「アンマネージリソースを持っている」=>「IDisposable を実装する」はほぼ正しいですが、逆の「IDisposable を実装する」=>「アンマネージリソースを持っている」は成立しません。「派生クラスでそういうリソースを扱うことが予想される基底クラス」(Stream など)や「Dispose パターンが扱いやすいから IDisposable を持っている」(IComponent など)といったパターンがあります。

    2 は、アンマネージリソースについてはその通りです(マネージリソースは、ファイナライザでは基本的に解放できません)。

    3 ですが、アプリケーション終了時のアンマネージリソースの解放はどちらかというと GC の仕事ではなく OS の仕事です。一応ファイナライザも解放処理を行いますが。
    Win32API の CreateFile を直接呼んでファイルハンドルを IntPtr で受け取っても、アプリケーション終了時にはファイルのロックは自動的に解除されます。ここに GC の動く余地はありません。
    ほかにも、強制終了されたときとか。
    また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。
    IDisposable を実装するもの全て、と言っておきましょう。
    // まあ静的メンバなんかは Dispose を呼び出すタイミングがないでしょうけど。
    2009年11月16日 5:08
  • >1.アンマネージリソースを扱うクラスは IDisposable インターフェイスを継承し、Dispose メソッドを実装している。

    厳密には、単に「扱う」のではなく、アンマネージリソースを「カプセルする」クラスが対象です。

    また、IDisposable インターフェースを実装する以上、IDisposable.Dispose() を実装していることは間違いありませんが、IDisposable インターフェースを明示的に実装する場合などに、public な Dispose() メソッドを持たせるかどうかはクラス設計者の判断に任されています。

    >2.仮に Dispose が実行されなかった場合でも、Finalize メソッド内で Dispose をコールするよう設計されている。

    そのようにクラスを設計することが「求められている」だけです。

    ランタイム側でそれを保証するすべはありません。

    >3.よって、ほとんどのアンマネージリソースは、アプリケーション終了時に GC によって安全に解放される筈である。

    YES ですが、その動作が本当に不適当でないかどうかは場合によりけりです。

    >また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。

    前項と重複しますが、危険≒不適当かどうかは場合によりけりな面もあるので、なんとも言い難いです。

    また、単純に「Dispose() しないと危険なクラス」を挙げたとしても、そのオブジェクトインスタンスの寿命がフレームワークなどによって管理されている場合、ユーザコード上でそのオブジェクトインスタンスが存在する意義を失っても、ユーザコードで安易に IDisposable.Dispose() 呼び出しを行うべきではない場合もあります。

    2009年11月16日 5:15
  • 「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。
    基本的にはないはずですが、もし存在するようなら、クラスの説明かDispose()メソッドの説明に明記されていると思います。具体的な例については思いつきません。
    .NET Framework 2.0からは必ず処理しておきたいアンマネージリソースを扱うためにCriticalFinalizerObjectクラス とその派生クラスが用意されています。Mutexクラスなんかがこれを使っています。
    それからPerformanceCounterクラスのCloseSharedResourcesメソッド のようにどうにも解放できないものは別途メソッドを用意していたりします。
    # といってもPerformanceCounterクラスはバグバグで使わない方がいいです。
    2009年11月16日 11:15
  • >> そのようにクラスを設計することが「求められている」だけです。
    >> ランタイム側でそれを保証するすべはありません。
    >
    >むmm? ここはどう捉えるべきでしょうか?
    >Dispose がコールされなかった場合、本来は Finalize 内で Dispose をコールする筈だが、
    >必ずしもそうなっているとは保証されてないと考えるべきでしょうか?

    そうです。だって、CLR は Finalizer を呼び出すだけですから。
    Finalizer 内で Dispose() を呼び出すのは、そのクラスの実装者の責任です。
    2009年11月17日 15:07
  • >この場合の 「実装者」 である MicroSoft が公開している、マネージリソースを扱うクラスであっても
    >Dispose() しなかった場合、Finalize 内で必ずしも Dispose がコールされているとは保証されてない
    >と考えてもいいのでしょうか?

    そうです。あったらイヤですが。

    >DbConnection は明示的に Close もしくは Dispose しろと書いてありました。

    微妙。

    この場合、Close() や DIspose() を明示的に呼び出すことが求められているというよりも、不要になった接続は速やかに解放するべし、くらいの意味のような気がします。
    (不安なら、原文も確認してみてください。僕は見てないけど (^^;)

    とは言え、「明示的に接続を閉じろ」と記載されていても、その上でさらに using 句を使用した方がいいでしょうね。(場面にもよりますが)

    ユーザコードで Close() 呼び出しを行っていたとしても、そこにたどり着くまでの間に例外が発生したら、Close() 呼び出しは行われません。
    2009年11月18日 1:29
  • >「Dispose をコールしている筈だけど、必ずしも保証はないよ」
    >と理解しておきます。(^ω^;

    この場合の「保証はない」は、可能性の話です。
    一般に、本来はそうあるべきではありません。

    「IDisposable インターフェースを実装するオブジェクトインスタンスが、(まだ)有効なアンマネージリソースを保持しているにも関わらず Finalizer 呼び出しでそれを解放しない」という実装は、Disposable パターンに適合していません。

    そのような実装は、普通に考えて(今度こそほんとの)リソースリークを引き起こすことが予想されるため、「設計/実装ミス」であると考えられます。

    >Environment.Exit 以外にも try ~ finally  等が無効になるケースってあるでしょうか?

    ワーカースレッドに対して、Thread.Abort をしつこく何度もかけたときとか?
    2009年11月18日 2:31
  • >おかげでかなり GC と Dipose と アンマネージリソースの関係について判ってまいりました。

    System.ComponentModel の話など、IDisposable.Dispose() より上流の話も出てしまいましたが、下のレイヤから順に消化していくことをお勧めします。

    過去の投稿で僕が(比較的注意深く)「単なる(クラスメンバとしての) Dispose()」と「IDisposable.Dispose()」を書き分けている点にも留意してみてください ;-)

    .NET では、アンマネージリソース(=ランタイムが管理するマネージメモリ以外のすべての資源)をカプセルするクラスは

    ・IDisposable インターフェースを実装し、IDisposable.Dispose() でそれを解放する。
    ・Finalizer 呼び出し時点で有効なアンマネージリソースを保持している場合、それを解放する。

    ことが求められています。

    前者は、ユーザコードやフレームワークなどから、オブジェクトインスタンスによってカプセルされたアンマネージリソースを明示的(意図的)、かつ速やかに解放するためのものです。

    # 「クラスメンバとして Dispose() メソッドを実装するべし」という規定ではない点に注意してください。

    「オブジェクトインスタンスがカプセルするアンマネージリソースの明示的な解放」の手続きを統一化することで、C# の using 構文などの導入が可能となります。

    後者は、ユーザコードやフレームワークなどによって解放される機会のなかったアンマネージリソースを解放するためのものです。

    # 「Finalizer 内で IDisposable.Dispose() を呼び出すべし」という規定ではない点に注意してください。

    Finalizer 呼び出しはガベージコレクション (GC) によってオブジェクトインスタンスが回収される際に行われるため、いつ賞味期限切れのオブジェクトインスタンスの Finalizer 呼び出しが行われるかは予測できません。

    また、ガベージコレクションによってどのような順番でオブジェクトインスタンスが回収されるのか、も予測することはできません。

    よって、オブジェクトインスタンスがカプセルするアンマネージリソースの解放を Finalizer 呼び出しにだけ頼るのは、原則として避けるべきでしょう。

    なお、これらはすべて「求められている」だけであり、実装者がそれらのルールを守らなかったことを検知するすべを .NET ランタイム(CLR)は持っていません。

    よって、IDisposable インターフェースを実装すること、およびそれが正しく機能することは、クラス設計者・実装者が責任をもたなくてはなりません。

    # CLR はクラスインスタンスがカプセルするアンマネージリソースの実体が何であるかを知らないため、至極当たり前の話ではあります。

    と、まずはここまでが .NET におけるアンマネージリソース(をカプセルするオブジェクトインスタンス)の寿命管理を考える上での根幹になります。

    それ以外の議論は、すべて上記の基本理念に基づいて導き出されたもの(あるいは、そこからさらに導きされたもの)であると思います。

    2009年11月20日 1:44
  • この記述おかしいですね。
    DbConnection は、適用範囲外では閉じられません。そのため、機能的に同等なCloseまたはDisposeを呼び出して、明示的に接続を閉じる必要があります。接続プールの値Poolingがtrueまたはyesに設定されている場合、これにより、物理的な接続も解放されます。
    connection poolが有効なら、Close()してもpoolに返されるはず。英語版も同じく。

    ついでにComponentのFilnalize()がDispose(false)を呼んでいます。
    この辺り、IDisposableではなくIComponentに従う必要があります。
    クラス、コンポーネント、コントロール
    2009年11月18日 4:00

すべての返信

  • 1 は、「マネージドなメモリ以外のリソースを扱うクラス」とすべきでしょう。マネージリソース(要するに IDisposable を実装するメンバ)を持つクラスも一般的に IDisposable を実装するのが普通です(StreamWriter など)。
    ちなみに、「アンマネージリソースを持っている」=>「IDisposable を実装する」はほぼ正しいですが、逆の「IDisposable を実装する」=>「アンマネージリソースを持っている」は成立しません。「派生クラスでそういうリソースを扱うことが予想される基底クラス」(Stream など)や「Dispose パターンが扱いやすいから IDisposable を持っている」(IComponent など)といったパターンがあります。

    2 は、アンマネージリソースについてはその通りです(マネージリソースは、ファイナライザでは基本的に解放できません)。

    3 ですが、アプリケーション終了時のアンマネージリソースの解放はどちらかというと GC の仕事ではなく OS の仕事です。一応ファイナライザも解放処理を行いますが。
    Win32API の CreateFile を直接呼んでファイルハンドルを IntPtr で受け取っても、アプリケーション終了時にはファイルのロックは自動的に解除されます。ここに GC の動く余地はありません。
    ほかにも、強制終了されたときとか。
    また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。
    IDisposable を実装するもの全て、と言っておきましょう。
    // まあ静的メンバなんかは Dispose を呼び出すタイミングがないでしょうけど。
    2009年11月16日 5:08
  • >1.アンマネージリソースを扱うクラスは IDisposable インターフェイスを継承し、Dispose メソッドを実装している。

    厳密には、単に「扱う」のではなく、アンマネージリソースを「カプセルする」クラスが対象です。

    また、IDisposable インターフェースを実装する以上、IDisposable.Dispose() を実装していることは間違いありませんが、IDisposable インターフェースを明示的に実装する場合などに、public な Dispose() メソッドを持たせるかどうかはクラス設計者の判断に任されています。

    >2.仮に Dispose が実行されなかった場合でも、Finalize メソッド内で Dispose をコールするよう設計されている。

    そのようにクラスを設計することが「求められている」だけです。

    ランタイム側でそれを保証するすべはありません。

    >3.よって、ほとんどのアンマネージリソースは、アプリケーション終了時に GC によって安全に解放される筈である。

    YES ですが、その動作が本当に不適当でないかどうかは場合によりけりです。

    >また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。

    前項と重複しますが、危険≒不適当かどうかは場合によりけりな面もあるので、なんとも言い難いです。

    また、単純に「Dispose() しないと危険なクラス」を挙げたとしても、そのオブジェクトインスタンスの寿命がフレームワークなどによって管理されている場合、ユーザコード上でそのオブジェクトインスタンスが存在する意義を失っても、ユーザコードで安易に IDisposable.Dispose() 呼び出しを行うべきではない場合もあります。

    2009年11月16日 5:15
  • 「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。
    基本的にはないはずですが、もし存在するようなら、クラスの説明かDispose()メソッドの説明に明記されていると思います。具体的な例については思いつきません。
    .NET Framework 2.0からは必ず処理しておきたいアンマネージリソースを扱うためにCriticalFinalizerObjectクラス とその派生クラスが用意されています。Mutexクラスなんかがこれを使っています。
    それからPerformanceCounterクラスのCloseSharedResourcesメソッド のようにどうにも解放できないものは別途メソッドを用意していたりします。
    # といってもPerformanceCounterクラスはバグバグで使わない方がいいです。
    2009年11月16日 11:15
  • 多くのご意見、誠にありがとうございます。<(_ _)>

    > ちなみに、「アンマネージリソースを持っている」=>「IDisposable を実装する」はほぼ正しいですが、
    > 逆の「IDisposable を実装する」=>「アンマネージリソースを持っている」は成立しません。
    > 「派生クラスでそういうリソースを扱うことが予想される基底クラス」(Stream など)や
    > 「Dispose パターンが扱いやすいから IDisposable を持っている」(IComponent など)といったパターンがあります。

    参考になります。
    確かに派生クラスで「リソースを扱うことが予想される」パターンというのは十分考えられますね。


    > 厳密には、単に「扱う」のではなく、アンマネージリソースを「カプセルする」クラスが対象です。

    なるほど・・・

    「アンマネージリソースをカプセル化する」

    これは大変しっくりくる表現です。頭にスッと入ってきます。

    最近パターンを「カプセル化」という観点から考えられないか、色々と考える機会が多いので、
    これは非常に判りやすい表現だと思います。ありがとうございます。


    皆様の返信は非常に面白い内容を含んでおりますが、
    ちょっと忙しくなってきましたので、続きはまた後でじっくり考えさせて頂きます。<(_ _)>

    2009年11月17日 1:49
    モデレータ
  • 2.仮に Dispose が実行されなかった場合でも、Finalize メソッド内で Dispose をコールするよう設計されている。

    Hongliang さん
    > アンマネージリソースについてはその通りです。

    渋木さん
    > そのようにクラスを設計することが「求められている」だけです。
    > ランタイム側でそれを保証するすべはありません。

    むmm? ここはどう捉えるべきでしょうか?
    Dispose がコールされなかった場合、本来は Finalize 内で Dispose をコールする筈だが、
    必ずしもそうなっているとは保証されてないと考えるべきでしょうか?
    2009年11月17日 8:28
    モデレータ
  • >> そのようにクラスを設計することが「求められている」だけです。
    >> ランタイム側でそれを保証するすべはありません。
    >
    >むmm? ここはどう捉えるべきでしょうか?
    >Dispose がコールされなかった場合、本来は Finalize 内で Dispose をコールする筈だが、
    >必ずしもそうなっているとは保証されてないと考えるべきでしょうか?

    そうです。だって、CLR は Finalizer を呼び出すだけですから。
    Finalizer 内で Dispose() を呼び出すのは、そのクラスの実装者の責任です。
    2009年11月17日 15:07
  • ちょっと昨日の質問では言葉が足りなくなってしまいましたが、
    そうです。だって、CLR は Finalizer を呼び出すだけですから。
    Finalizer 内で Dispose() を呼び出すのは、そのクラスの実装者の責任です。
    ということは・・・・・・

     「.NET Framework の標準的なクラス」  

    この場合の 「実装者」 である MicroSoft が公開している、マネージリソースを扱うクラスであっても
    Dispose() しなかった場合、Finalize 内で必ずしも Dispose がコールされているとは保証されてない

    と考えてもいいのでしょうか?


    Hongliang さん
    3 ですが、アプリケーション終了時のアンマネージリソースの解放はどちらかというと GC の仕事ではなく OS の仕事です。一応ファイナライザも解放処理を行いますが。
    Win32API の CreateFile を直接呼んでファイルハンドルを IntPtr で受け取っても、アプリケーション終了時にはファイルのロックは自動的に解除されます。ここに GC の動く余地はありません。
    ほかにも、強制終了されたときとか。

    渋木さん
    >3.よって、ほとんどのアンマネージリソースは、アプリケーション終了時に GC によって安全に解放される筈である。

    YES ですが、その動作が本当に不適当でないかどうかは場合によりけりです。

    >また、「このクラスは明示的に Dispose をしないと危険」 というクラスも合わせて教えて頂けるとありがたいです。

    前項と重複しますが、危険≒不適当かどうかは場合によりけりな面もあるので、なんとも言い難いです。

    なるほど、確かに強制終了された場合は、GC の関与する余地はありませんよね。また場合によりけりと。。。
    これで GC は万能ではないということがよく判りました。


    佐祐理さん

    > 基本的にはないはずですが、もし存在するようなら、クラスの説明かDispose()メソッドの説明に明記されていると思います。
    > 具体的な例については思いつきません。

    データベースコネクション絡みは以前から気になっていたので、改めて調べてみました。
    DbConnection は明示的に Close もしくは Dispose しろと書いてありました。以下引用です。
    DbConnection は、適用範囲外では閉じられません。そのため、機能的に同等な Close または Dispose を呼び出して、明示的に接続を閉じる必要があります。接続プールの値 Poolingtrue または yes に設定されている場合、これにより、物理的な接続も解放されます。
    2009年11月17日 17:08
    モデレータ
  • >この場合の 「実装者」 である MicroSoft が公開している、マネージリソースを扱うクラスであっても
    >Dispose() しなかった場合、Finalize 内で必ずしも Dispose がコールされているとは保証されてない
    >と考えてもいいのでしょうか?

    そうです。あったらイヤですが。

    >DbConnection は明示的に Close もしくは Dispose しろと書いてありました。

    微妙。

    この場合、Close() や DIspose() を明示的に呼び出すことが求められているというよりも、不要になった接続は速やかに解放するべし、くらいの意味のような気がします。
    (不安なら、原文も確認してみてください。僕は見てないけど (^^;)

    とは言え、「明示的に接続を閉じろ」と記載されていても、その上でさらに using 句を使用した方がいいでしょうね。(場面にもよりますが)

    ユーザコードで Close() 呼び出しを行っていたとしても、そこにたどり着くまでの間に例外が発生したら、Close() 呼び出しは行われません。
    2009年11月18日 1:29
  • >この場合の 「実装者」 である MicroSoft が公開している、マネージリソースを扱うクラスであっても
    >Dispose() しなかった場合、Finalize 内で必ずしも Dispose がコールされているとは保証されてない
    >と考えてもいいのでしょうか?

    そうです。あったらイヤですが。

    なるほど・・・よくわかりました。

    「Dispose をコールしている筈だけど、必ずしも保証はないよ」

    と理解しておきます。(^ω^;

    >DbConnection は明示的に Close もしくは Dispose しろと書いてありました。

    微妙。

    この場合、Close() や DIspose() を明示的に呼び出すことが求められているというよりも、不要になった接続は速やかに解放するべし、くらいの意味のような気がします。
    (不安なら、原文も確認してみてください。僕は見てないけど (^^;)
    英文の方を覗いてみました。

    「you must explicitly close the connection by calling Close or Dispose」

    must explicitly ・・・せねばならない・・・明らかに・・・

    これはかなり強い表現ですね。(^ω^;


    私としては try ~ finally や using で、
    必ず Close もしくは Dispose を実行するようコーディングを心がけてますが、
    (もちろん、インスタンスの寿命が管理されている場合は除きますが・・・)
    先日の佐祐理さんのレスで、初めて Environment.Exit で
     finally ブロックを通過せずにアプリケーションを強制終了できてしまうことを知りました。

    Environment.Exit 以外にも try ~ finally  等が無効になるケースってあるでしょうか?
    2009年11月18日 2:07
    モデレータ
  • >「Dispose をコールしている筈だけど、必ずしも保証はないよ」
    >と理解しておきます。(^ω^;

    この場合の「保証はない」は、可能性の話です。
    一般に、本来はそうあるべきではありません。

    「IDisposable インターフェースを実装するオブジェクトインスタンスが、(まだ)有効なアンマネージリソースを保持しているにも関わらず Finalizer 呼び出しでそれを解放しない」という実装は、Disposable パターンに適合していません。

    そのような実装は、普通に考えて(今度こそほんとの)リソースリークを引き起こすことが予想されるため、「設計/実装ミス」であると考えられます。

    >Environment.Exit 以外にも try ~ finally  等が無効になるケースってあるでしょうか?

    ワーカースレッドに対して、Thread.Abort をしつこく何度もかけたときとか?
    2009年11月18日 2:31
  • この記述おかしいですね。
    DbConnection は、適用範囲外では閉じられません。そのため、機能的に同等なCloseまたはDisposeを呼び出して、明示的に接続を閉じる必要があります。接続プールの値Poolingがtrueまたはyesに設定されている場合、これにより、物理的な接続も解放されます。
    connection poolが有効なら、Close()してもpoolに返されるはず。英語版も同じく。

    ついでにComponentのFilnalize()がDispose(false)を呼んでいます。
    この辺り、IDisposableではなくIComponentに従う必要があります。
    クラス、コンポーネント、コントロール
    2009年11月18日 4:00
  • 渋木さん
    > この場合の「保証はない」は、可能性の話です。
    > ・・・中略・・・
    > そのような実装は、普通に考えて(今度こそほんとの)リソースリークを引き起こすことが予想されるため、「設計/実装ミス」であると考えられます。

    なろほどです。


    > ワーカースレッドに対して、Thread.Abort をしつこく何度もかけたときとか?

    マルチスレッドはかな~り昔・・・Delphi で少しやっただけなので、かなり忘れてますが、
    機会見てこの辺も色々調べてみたいと思います。


    佐祐理さん
    > connection poolが有効なら、Close()してもpoolに返されるはず。英語版も同じく。

    そうなんですか?コネクションプールは概略しか掴めてないので、この辺イマイチピンと来てないのが現状です。
    これも機会を見てしっかり抑えたいと思います。

    あと
    > クラス、コンポーネント、コントロール

    参考になるリンクありがとうございます。<(_ _)>
    おかげでかなり GC と Dipose と アンマネージリソースの関係について判ってまいりました。


    いずれにせよ皆様貴重な情報ありがとうございました。
    まだ一部のリンク先を読み切れてない状況ですが、いったんこれにてこのスレを収束させていただきます。
    また判らない点、不明な点が出てきたら、新規にスレッド起して質問させて頂きたいと思います。<(_ _)>

    2009年11月19日 16:09
    モデレータ
  • >おかげでかなり GC と Dipose と アンマネージリソースの関係について判ってまいりました。

    System.ComponentModel の話など、IDisposable.Dispose() より上流の話も出てしまいましたが、下のレイヤから順に消化していくことをお勧めします。

    過去の投稿で僕が(比較的注意深く)「単なる(クラスメンバとしての) Dispose()」と「IDisposable.Dispose()」を書き分けている点にも留意してみてください ;-)

    .NET では、アンマネージリソース(=ランタイムが管理するマネージメモリ以外のすべての資源)をカプセルするクラスは

    ・IDisposable インターフェースを実装し、IDisposable.Dispose() でそれを解放する。
    ・Finalizer 呼び出し時点で有効なアンマネージリソースを保持している場合、それを解放する。

    ことが求められています。

    前者は、ユーザコードやフレームワークなどから、オブジェクトインスタンスによってカプセルされたアンマネージリソースを明示的(意図的)、かつ速やかに解放するためのものです。

    # 「クラスメンバとして Dispose() メソッドを実装するべし」という規定ではない点に注意してください。

    「オブジェクトインスタンスがカプセルするアンマネージリソースの明示的な解放」の手続きを統一化することで、C# の using 構文などの導入が可能となります。

    後者は、ユーザコードやフレームワークなどによって解放される機会のなかったアンマネージリソースを解放するためのものです。

    # 「Finalizer 内で IDisposable.Dispose() を呼び出すべし」という規定ではない点に注意してください。

    Finalizer 呼び出しはガベージコレクション (GC) によってオブジェクトインスタンスが回収される際に行われるため、いつ賞味期限切れのオブジェクトインスタンスの Finalizer 呼び出しが行われるかは予測できません。

    また、ガベージコレクションによってどのような順番でオブジェクトインスタンスが回収されるのか、も予測することはできません。

    よって、オブジェクトインスタンスがカプセルするアンマネージリソースの解放を Finalizer 呼び出しにだけ頼るのは、原則として避けるべきでしょう。

    なお、これらはすべて「求められている」だけであり、実装者がそれらのルールを守らなかったことを検知するすべを .NET ランタイム(CLR)は持っていません。

    よって、IDisposable インターフェースを実装すること、およびそれが正しく機能することは、クラス設計者・実装者が責任をもたなくてはなりません。

    # CLR はクラスインスタンスがカプセルするアンマネージリソースの実体が何であるかを知らないため、至極当たり前の話ではあります。

    と、まずはここまでが .NET におけるアンマネージリソース(をカプセルするオブジェクトインスタンス)の寿命管理を考える上での根幹になります。

    それ以外の議論は、すべて上記の基本理念に基づいて導き出されたもの(あるいは、そこからさらに導きされたもの)であると思います。

    2009年11月20日 1:44
  • > System.ComponentModel の話など、IDisposable.Dispose() より上流の話も出てしまいましたが、下のレイヤから順に消化していくことをお勧めします。

    ・・・(中略)・・・

    > と、まずはここまでが .NET におけるアンマネージリソース(をカプセルするオブジェクトインスタンス)の寿命管理を考える上での根幹になります。

    > それ以外の議論は、すべて上記の基本理念に基づいて導き出されたもの(あるいは、そこからさらに導きされたもの)であると思います。

    おぉ!これはありがとうございます!!(^ω^)
    このレスを参考に、もう一回スレッド全般並びに関連記事をおさらいしたいと思います。
    本当にありがとうございました!!

    2009年11月20日 2:01
    モデレータ