- PR -

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

投稿者投稿内容
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-10-28 21:27
引用:

例えば、SqlConnection メンバや、StreamWriter メンバには、
パブリック メソッドの中にCloseとDisposeが両方います。
この場合、使用する側の理解としては、以下のどれが正しいのでしょうか?



その2つのクラスを同一に扱おうとしている時点でNGです。

両クラスの設計思想は異なります。

SqlConnection.Close() は SqlConnecton.Close() 相当の働きを持っていることがヘルプで述べられていますが、StreamWriter.Close() ではまったく事情が異なります。


[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-10-28 21:46 ]
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-10-28 22:21
え〜、じゃあClose()とDisose()を両方実装したクラスに出会うたびに、いちいち仕様書確認して、
前述のA〜Cのどれが一番適切か判断しなきゃいけないってことですか?
いちいちそんなことやってられないっすよ〜。
結果論でもいいんで、「こう書いときゃまず間違いない」ってゆう書き方はないんですか?

#わざと頭悪そーな感じで書いてみました。ご了承ください。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-10-28 23:19
引用:

ぼのぼのさんの書き込み (2006-10-28 22:21) より:
え〜、じゃあClose()とDisose()を両方実装したクラスに出会うたびに、いちいち仕様書確認して、
前述のA〜Cのどれが一番適切か判断しなきゃいけないってことですか?
いちいちそんなことやってられないっすよ〜。
結果論でもいいんで、「こう書いときゃまず間違いない」ってゆう書き方はないんですか?

#わざと頭悪そーな感じで書いてみました。ご了承ください。


残念ながら、そうやらなきゃダメです。
また、反対にクラスを作るときには、そのあたりを明記しなければダメです。
_________________
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-10-29 02:43
引用:

いちいちそんなことやってられないっすよ〜。



ご武運を。


[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2006-10-29 03:33 ]
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-10-29 08:48
StreamWriterのCloseはDisposeを呼び出すんですねぇ。
StreamWriterにはOpenが無いから、
開いて閉じてまた開くって操作を想定してないわけで、
Closeするってことは、このインスタンスを使って書き込むことはもう無いよ、
ってことになるので、これは合点がいきます。
A〜Cのどれが適切かっていえば、「どれでもOK」って感じですね。

一方、SqlConnectionですが、これはDispose⊃Closeって考えて良いのかな?
こっちはOpenがあるから開いて閉じてまた開くって操作は想定されるわけで、
Closeで接続文字列の情報とか解放しちゃったらOpenできなくなっちゃいますもんね。

で、「もうこれ以上は使わないよ」って状態になったら、
やっぱDisposeが一番適切ってことになるんでしょうか?
でも、即座に解放してほしいアンマネージドリソースであるDB接続は、
Closeでも解放されるわけで、他のリソースは別に即座に解放されなくてもいいや
って考えるなら、CloseのみだってOKですよね。

となると、A〜Cのどれが適切かっていえば、やっぱ「どれでもOK」?

#いいのかそんな結論で
object
ぬし
会議室デビュー日: 2002/03/20
投稿数: 338
お住まい・勤務地: 香川県高松市
投稿日時: 2006-10-29 11:44
objectです。

参考になればと思い、少し簡単に発言します。

問題を「Dispose」だけで無く
「delete(デストラクタ)」、「finalize」、「close、dispose」
という観点から考え直す必要があると思います。
#便宜的にdelete(デストラクタ)表現しました。

私は、基本的には
「new」したものは、必ず「delete」すべき
つまり「完全に管理すべき」だと思っています。
#「デストラクト」が空であっても、管理する側としては当然明示的に呼ぶべき。

問題は
「デストラクタ=finalize」
と考える事にあるのではないでしょうか?

私は
「GC」は文字通り「ゴミ集め」
つまり、
「デストラクト」されたものを最終処理するのが「GC」
だと思っています。
#勿論、「GC」のタイミングでリークしているメモリを開放するのは利に適っています。
#今は「デストラクタ」の存在が自動的に「finalize処理」に繋がっていますがこれも問題?

「デストラクト」を「finalize」で歪め、その不足を「dispose」で補おう
という考え方をするから、問題が起きているのではないでしょうか?
※『「dispose」補おう⇒「dispose」で補おう』に修正

[ メッセージ編集済み 編集者: object 編集日時 2006-10-29 14:03 ]
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2006-10-29 14:30
引用:

objectさんの書き込み (2006-10-29 11:44) より:
問題は
「デストラクタ=finalize」
と考える事にあるのではないでしょうか?


いつもながら定義が間違っていると思う。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-10-29 18:59
引用:

私は、基本的には
「new」したものは、必ず「delete」すべき
つまり「完全に管理すべき」だと思っています。


うーん、これはC++的な考え方であって、#な考え方ではないですよね。
なんてゆーか、オートマ車を運転してる人にクラッチの上手な使い方を力説してるような感じがします。

それに、Finalizeまで考えなきゃいけないのは、
自分でアンマネージドリソースを扱うクラスを作る場合ですよね。
既存のクラスを使う分には、
「お、このクラスにはDisposeがあるぞ。どれどれ仕様書を見てみよう。
 む、Closeもあるぞ。あ、でもこのクラスのCloseはDisposeと同じなのか。
 じゃあどっちか片方だけ呼んどきゃいいわけだ。せっかくだからUsing使うか」
ってレベルでいいと思うんですが。

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