- PR -

Dispose の意味が未だわからないのですが

投稿者投稿内容
ハルシオン
常連さん
会議室デビュー日: 2005/03/29
投稿数: 24
投稿日時: 2006-10-26 22:07
いつもお世話になっております。

今更ながらどうしても気になることがありますので恥を忍んで
質問させてください。

質問は「Dispose」のことです。
以下スレッドでスレ主さんも「Dispose」について質問されており
同様に意味を理解できていなかった私は成り行きを楽しみに見守っていたわけなんですが、
一向にわかりません。

というか、謎が深まるばかりなのです。
一体、何をしているのか?
何のために finally などで「Dispose」をすることを保障するコーディングをしなきゃいけないのか?


【インスタンス開放のタイミングについて】
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26233&forum=7


【変数に対するメモリの使い方について】
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=31217&forum=7


上記2つのスレッドより、皆様の発言を勝手ながらかいつまんで以下に転載させて頂きました。


引用:



Disposeについて

(囚人さんの書き込みより)
・GC に任せないで、早急に解放すべき「リソース」を解放するときに Dispose() を使います。
(かるあさんの書き込みより)
・Dispose を実装しているメソッドはその必要があるから実装しているのだと思います。
 データベースのコネクションなどは使ったら他の人のために
 すぐにコネクションプールに戻してあげる必要がありますよね
・Dispose() はアンマネージドリソースの開放を行ってもらうためにあります
(なちゃさんの書き込みより)
・Disposeとメモリは「基本的には」関係ありません。
(Jittaさんの書き込みより)
・Dispose は、何も「解放」だけを取り扱いません。これには、「適当に処置する」という意味があります。 
使用することを終わったために“後片付けを適切に行う”ととらえれば、 
何もメモリを解放することにこだわることがなくなりませんか?





やっぱりなんとなくわからない…。

ここでようやく私の抱いている質問なのですが、

1)アンマネージリソースとはいったいどのようなものを指すのか?
  上記の話の流れから勝手に推察すると、『CLRの管理下で動作していないリソース』のようなもの?

2)「Dispose」を行わなければいけない場合はどのような場合なのか?
  上記スレッドでは、かるあさんが「DBのコネクション」の例を挙げてくださっていますので、これ以外で…。
  それは一体なぜなのでしょう?
  (アンマネージリソースだからなのか!?)

3)アンマネージリソースを「Dispose」で明示的に「あと片付け」してやらなければいけない理由は一体何か?
  これは、「Dispose」しないとどうなってしまうのか?と言う疑問に結びついていきます。



初歩的なことな上に、「何がわからない」かもぼんやりしている状況ですが、今ココで放置しておいても
結局未来永劫に理解するチャンスは訪れないだろうと思い質問させていただきました。


質問内容が漠然としすぎているかもしれませんが、ヒントになりそうな記事等でも結構です。
何か理解に至る良きアドバイスお願い致します。
  

#ちなみに私が学習している言語はVB.NETです。
 C#は書けません。少しだけ読める程度の知識です。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2006-10-26 22:41
まあ分かりやすいのがファイルでしょう。
ファイルを読んでる途中に余所から書き込まれると困りますよね? ですから「俺が読んでる最中だから他の奴らは書くな」と書き込みを禁じます。
しかしこのまま放っておいては誰も書き込めない困ったファイルになってしまいます。そのため、書き込み禁止した人は責任を持って書き込み禁止を解除しなければなりません。

CLR が管理するのは(マネージドなものは)基本的にメモリのみです。
当然のことながらファイルはメモリではないので管理してくれません。
ファイルを開いた人は責任を持って閉じる必要があり、CLR が勝手に閉じてはくれません。

さて、メモリとは別の表現をすればオブジェクトです。
.NET にはファイルを扱うクラスが存在し、それを通してファイルにアクセスします。
例えば一般的にはファイルを開くのには FileStream クラスを使用し、このコンストラクタにファイル名やモードを渡して FileStream オブジェクトを作成します。
作成された FileStream はオブジェクトでつまりメモリですから、マネージドである事になります。
マネージドですからほっておけばそのうち勝手にお掃除されます(ガベージコレクト)。
一般的にはこのときファイルも閉じられます。ガベージコレクトされるってことはもうその FileStream を使える人がいないって事で、それはつまりもうファイルも開いてる意味が無くなると言う事ですから。もっともこれはあくまで FileStream の内部で行われているだろう事を想像するだけですが。
基本的にアンマネージドな物が直接目に触れることってのは無いはずです。ファイルというアンマネージドなリソースもこのように FileStream というマネージドなリソース(要するにオブジェクト)でラップされて、ファイルの開閉は必ずしも意識しなくてもオブジェクトと寿命を共にします。

問題は、ガベージコレクションはこちらが操作するんではなく、ランタイムが必要な時に勝手に実行する物である事です。ある程度ゴミが溜まってから一気に行われます。とあるオブジェクトを誰も見なくなっても、それはガベージコレクションの対象になるだけであって、オブジェクトが消えるのは「そのうち」です。
メモリに関しては、別にこのモデルでもなんの問題もありません。メモリは代わりがきくものですから、このメモリが使えないのならとなりのメモリを使えばいいのですし。

しかし、ファイルとなるとそう言うわけにも生きません。読み込み終了したらすぐ削除したくても、ガベージコレクション任せでは、いつ書き込み禁止が解けて削除可能になるかは全く予測が付かないのですから。ひょっとしたらプロセス終了までずっと抱え込んでるかも知れません。

ということで、そのための Dispose です。
ognac
ベテラン
会議室デビュー日: 2005/06/21
投稿数: 65
投稿日時: 2006-10-27 01:10
ognacといいます。
後始末処理の重要性と認識したほうが理解できるかと思います。
Win32リソース(非Net)でDC(デバイスコンテキスト)等を扱うときは,必ずリリースが要りますよね。
これを忘れるとメモリーリークの元になりますよね。
 注意していてもリリース忘れが起こってしまいがちです。その防止策という意味でも,Finaly/Disposeの活用があります。
リソース以外にも,自分で定義した資源の初期状態への復帰でも使えますね。
そのクラスで使用した他のobjectを元の姿に戻してお返しする。など。

Usingで括れば, End Usingのタイミングで Disposeが呼ばれますので, Classが確り作っていれば、後始末を考えなくてすむ分、楽になります。

ちなみに, usingの後ろは n個の newが記述できるので,ネストが深まることもありません。
例) using x as new cls1, y as new cls2, z as new cls3
end using


_________________
ognac@わんくま同盟

[ メッセージ編集済み 編集者: ognac 編集日時 2006-10-27 01:17 ]
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-10-27 09:25
引用:

ハルシオンさんの書き込み (2006-10-26 22:07) より:

ここでようやく私の抱いている質問なのですが、

1)アンマネージリソースとはいったいどのようなものを指すのか?
  上記の話の流れから勝手に推察すると、『CLRの管理下で動作していないリソース』のようなもの?

2)「Dispose」を行わなければいけない場合はどのような場合なのか?
  上記スレッドでは、かるあさんが「DBのコネクション」の例を挙げてくださっていますので、これ以外で…。
  それは一体なぜなのでしょう?
  (アンマネージリソースだからなのか!?)

3)アンマネージリソースを「Dispose」で明示的に「あと片付け」してやらなければいけない理由は一体何か?
  これは、「Dispose」しないとどうなってしまうのか?と言う疑問に結びついていきます。


上記の疑問を見ると、マネージドリソースとは?、に関してもう一度ご確認された方が宜しいように感じました。
Jittaさんのブログに分かりやすい説明がありますので、ご参考になさって下さい。

http://blogs.wankuma.com/jitta/archive/2006/02/21.aspx

補足として、対象オブジェクトが Dispose を実装している場合は、かならず Dispose してあげるようにしています。
何故なら、Dispose を実装している理由があると考えるからです。

同様に、ラッピングした場合も、IDisposable を実装して、Dispose を実行させるようにします。
_________________
R・田中一郎 @ わんくま同盟  -  R.Tanaka.Ichiro’s Blog ← ブログはじめました


[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-10-27 11:15 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-10-27 09:43
引用:

R・田中一郎さんの書き込み (2006-10-27 09:25) より:

補足として、対象オブジェクトが Dispose を実装している場合は、かならず Dispose してあげるようにしています。
何故なら、Dispose を実装している理由があると考えるからです。


理由がない (仕方なく) というのもありますけどね。
多くのは場合は、精神衛生上の問題だろうと思います。
Stream 系は、この限りでないです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-10-27 11:24
脱線します(でも、ちょっと絡むからOK)

Open俺() と言うメソッドを作った場合、必ず Close俺() メソッドを作りますね。
例え、Close俺() で何もしないとしても、です。
こうすると使う側に精神的な負担をかけずに済みますね。
(入力の負担はかかりますが)

そういうことでしょうか?>精神衛生上の問題

_________________
R・田中一郎 @ わんくま同盟  -  R.Tanaka.Ichiro’s Blog ← ブログはじめました


[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-10-27 11:26 ]
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-10-27 11:58
引用:

同様に、ラッピングした場合も、IDisposable を実装して、Dispose を実行させるようにします。



IDisposable.Dispose() を「いつ呼び出すべきか」は状況によって異なります。

あるクラスが、メンバ変数として IDisposable.Dispose() を実装するクラスのインスタンスを保持するような場合、そのクラスの IDisposable.Dipose() で「メンバ変数の IDisposable.Dispose() を必ず呼び出す」のは常に正しいとは限りません。

なので、そういったコーディングを慣習化するのはあまり好ましいと思えません。
(テスト段階で不備が発覚するとは思いますが)

また、IDisposable を実装するクラスを継承する場合でも、そのクラスに Dispose(bool disposed) のようなインフラが整備されている場合は、基底クラスが実装する IDisposable.Dispose() を直接呼び出すのではなく、Dispose(bool dispose) を使用するのが正道と思います。
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2006-10-27 12:20
とりあえず、MSDN 内の Dispose に関する記述

アンマネージ リソースのクリーンアップ
http://msdn2.microsoft.com/ja-jp/library/498928w2.aspx

アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装
http://msdn2.microsoft.com/ja-jp/library/b1yfkh5e.aspx

IDisposable.Dispose メソッド
http://msdn2.microsoft.com/ja-jp/library/system.idisposable.dispose.aspx

スキルアップ/キャリアアップ(JOB@IT)