using(StreamReader sr = new StreamReader(...))
{
...
}
using ブロックを使った際(Dispose() が呼ばれれば)、StramReader.Close() は呼ばなくていいみたいなんですが、自分なりに「何故?」が説明できなかったので調べてみました。
#Dispose calls Close?
とりあえず真っ先に思いついたのが、「 Dispose() の中で Close() が呼ばれているから?」
さっそくMSDNに確認をとってみたところ...
StreamReader.Dispose()
この TextReader オブジェクトによって使用されているすべてのリソースを解放します。 (TextReader から継承されます。)
おやおや?
StreamReader の Dispose() は、親クラスである TextReader の Dispose() をそのまま呼んでいるご様子。
TextReader が派生先の StreamReader のリソースをいじれるとはちょっと考えにくいです。
#StreamReader.Close() を調べてみると
StreamReader.Close()
StreamReader オブジェクトと、その基になるストリームを閉じ、リーダーに関連付けられたすべてのシステム リソースを解放します。 (TextReader.Close() をオーバーライドします。)
これは大変です。
このリファレンスを信じるならば、StreamReader は Close() を呼ばない限り適切な解放処理が行われないことになります。
#StreamReader.Dispose(Boolean)
どないなっとんねん~と思いながら、さらにリファレンスを漁っていると、こんなメソッドが
StreamReader.Dispose(Boolean)
基になるストリームを閉じ、StreamReader によって使用されているアンマネージ リソースを解放します。任意でマネージ リソースも解放します。 (TextReader.Dispose(Boolean) をオーバーライドします。)
おや、こっちの Dispose はリソース解放を行うようです。
ちょっと詳しく見てみましょう。
This method is called by the public Dispose method and the Finalize method. Dispose invokes the protected Dispose method with the disposing parameter set to true.
このメソッドは public メソッドの Dispose() および Finalize() から呼び出されます。 Dispose() は Dispose(Boolean) に true を渡して呼び出します。
...どうやら、犯人が見つかったようです。
#結論
つまりこういうことでした。
- using句の終端に到達する
- Dispose()が呼ばれる
- Dispose()内でDispose(Boolean)が呼ばれる
- Dispose(Boolean)内でリソースの解放などが行われる
- めでたしめでたし
知らなくても exe は動きます。
でもどうせなら、何で動くか知った上で使いたいですよね。
・・・ところで、Dispose(Boolean) 内でリソースの解放を行っているようですが、Close() との関連性はどうなってるんでしょう。
Dispose(Boolean) の中で Close() を呼んでるんでしょうか?
それもと、Close() が Dispose(Boolean) を呼んでるんでしょうか?
というか、そもそも Dispose(Boolean) と Close() で行っている解放処理は同じモノなのでしょうか?
まだモヤモヤが晴れない部分が残りますね。
次回はそこをスッキリさせようと思います。