StreamReader.Close()を呼ばなくていい理由

# はじめに

StreamReaderは、使い終わったら ```Close()``` を呼び出してストリームを閉じる必要があります。
しかし、usingブロックを使用した場合は、明示的に ```Close()``` を呼ばなくても自動的にストリームが閉じられます。

```c#:基本
StreamReader sr = new StreamReader(...);
sr.Read();
sr.Close();
```

```c#:usingを使用する場合
using(StreamReader sr = new StreamReader(...))
{
    sr.Read();
}
```

これは何故でしょうか？
ちょっと調べてみました。

# usingブロックとは

usingブロックは、```IDisposableインタフェース``` を実装したインスタンスの ```Dispose()``` を、ブロック終端到達時に自動的に呼び出してくれる便利文法です。

```StreamReader``` は ```IDisposableインターフェース``` を実装してるので、usingブロックで ```Dispose()``` を呼び出してもらうことができます。

# Dispose() の中で Close()？

さて、usingを用いることで ```StraemReader.Dispose()``` が自動的に呼び出されますが、それだけでは ```StreamReader.Close()``` は呼び出されません。

では、```Dispose()``` の中で ```Close()``` が呼ばれているのでしょうか？

そこで、```StreamReader.Dispose()``` を [MSDN](http://msdn.microsoft.com/ja-jp/library/system.io.streamreader(v=vs.110).aspx) で調べてみたところ。

> *StreamReader.Dispose()*
> このTextReaderオブジェクトによって使用されているすべてのリソースを解放します。 (TextReader から継承されます。)

```StreamReader.Dispose()``` は、親クラスである ```TextReader``` のリソースを解放しているだけのようです。

では、```StreamReader``` のリソース解放はどこで行われるのでしょうか？

# StreamReader.Dispose(Boolean)

さらに ```StreamReader``` のリファレンスを調べてみると、```StreamReader.Dispose(Boolean)```という、```Dispose()``` のオーバーロードが見つかりました。

> *StreamReader.Dispose(Boolean)*
> 基になるストリームを閉じ、StreamReader によって使用されているアンマネージド リソースを解放します。任意でマネージド リソースも解放します。

どうやら ```Dispose(Boolean)``` を呼び出せば、リソースの解放が行われるようです。
しかし、usingは ```Dispose()``` を呼び出すだけなので、このメソッドには行きつかないはずです。

ところが、[注釈](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.dispose#remarks)の欄に以下のようなことが書いてありました。
（日本語ページは翻訳がエキサイト[^1]だったので英文を引用）

[^1]:訳文がめちゃくちゃって意味です。「エキサイト翻訳」って言葉、もう通じないかな…？(´・ω・`)

> This method is called by the public Dispose method and the Finalize() method, if it has been overridden. Dispose invokes the protected Dispose method with the disposing parameter set to true. Finalize invokes Dispose with disposing set to false.

意訳すると…

> **このメソッドは Dispose() および Finalize() から呼び出されます。**
> **Dispose() は Dispose(Boolean) に true を渡して呼び出します。**
> Finalize() は Dispose(Boolean) に false を渡して呼び出します。

とても大切なことが、こんなところに書いてありました。
Dispose()のリファレンスにも書いておいてほしいですね。

# 結論

usingブロックを用いた場合、以下の流れで ```StreamReader``` のリソースが解放されるようです。

1. usingブロック終端で ```StreamReader.Dispose()``` が呼ばれる。
1. ```StreamReader.Dispose()``` の内部で ```StreamReader.Dispose(true)``` が呼ばれる。
1. ```StreamReader.Dispose(true)``` にて ```StreamReader``` のリソース解放処理が行われる。

```Close()```を呼ばなくてもリソースが解放されるのは、こういう仕組みだったからのようですね。

# 補足

さて、Close()を呼ばなくてもリソース解放処理が安全に走る理由は分かりました。
しかしそうなると、

* ```Close()``` はなんのために存在しているの？
* ```Dispose()```と```Close()```はどういう使い分けをすればいいの？

という疑問にぶつかります。

これについて、皆さまからコメントをいただきましたので、ここにまとめさせていただきます。

1. .NET1.1では、外部リソースを取り扱う処理は ```Open()``` と ```Close()``` を用いてリソースの取得／解放を行うのが主流だった。

1. しかし、.NET2.0で[Disposeパターン](https://learn.microsoft.com/ja-jp/dotnet/standard/garbage-collection/implementing-dispose?redirectedfrom=MSDN)が確立される従い、```Open()```／```Close()``` は、コンストラクタ／```Dispose()``` の中に埋め込まれるようになる。

1. さらにDisposeパターンが浸透するにつれ、「リソース解放処理の主体は```Dispose()```であり、```Dispose()```で処理を実装するべき」という思想に変わっていく。

1. これにより、```Close()```の解放処理は```Dispose()```に移された。

1. 既存ソースとの互換性を確保するため、 ```Close()``` も引き続き公開されることになる。ただし、実装自体は内部で ```Dispose()``` を呼び出すだけになった[^2]。

このような歴史的経緯があるそうです。
@ngyukiさん、@kuchikiosさん、@matarilloさん、ご助言ありがとうございました。

[^2]:[StreamReader.Close()の注釈](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.close#remarks)にも書いてありますね。