using文で初期化したDbConnection、Closeを書くべき？書かなくていい？


# はじめに

DBとのコネクションのために利用するDbConnectionクラス。

このクラスをusing文で初期化したならば、Close処理を良しなにやってくれそうなので、Closeメソッドの記述は不要だと思っていたのですが、Closeメソッドを記述しているソースコードを散見しました。

例

```sample-dbclose.cs
using (DBEntities db = DbContext.CreateContext())
{
    db.Database.Connection.Open();
    // dbを使った処理
    db.Database.Connection.Close();  // Closeを明記している
}
```

結局、要るのか要らないのか調査しました。

# はじめに結論

**DBコネクションを1度閉じてusingスコープ内で再OpenするならばCloseを書くべし。それ以外は不要(あってもなくても良い)。**

その理由を以下に説明していきます。

# 理由

## using文とは

そもそもusing文とは何ものなのかという話。

[こちらの公式ドキュメント](https://msdn.microsoft.com/ja-jp/library/yh598w02(v=vs.110).aspx)によると、

> IDisposable オブジェクトの正しい使用を保証する簡易構文を提供します。 

using文は、IDisposableインターフェースを実装したクラス(Disposeメソッドを実装している)でないと利用できません。

利用例を見てみます。

```sample-using.cs
using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}
```

`Font`クラスはIDisposableインターフェースを実装しているクラスなので、using文の中で初期化が可能です。

そして、コンパイラはこのusing文を以下のように展開します。

```sample-using-extended.cs
{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}
```

using文は、`try {} finally {XXX.Dispose();}`をわざわざ書かなくてすむようにする糖衣構文ということです。

なので、using文で初期化されたインスタンスは必ずDisposeされることが保証されています。

DbConnectionクラスはIDisposableインターフェースを実装したComponentクラスを継承しているので、using文で初期化することで最後はDisposeされます。

## Closeメソッドとは

[こちらの公式ドキュメント](https://msdn.microsoft.com/ja-jp/library/system.data.common.dbconnection.close(v=vs.110).aspx)によると、

> you must explicitly close the connection by calling Close or Dispose, which are functionally equivalent.

functionally equivalentとあるように、 **DbConnectionクラスにとっては、機能的にはCloseもDisposeもどちらも変わらない** ということです。

なので、using文ではDisposeメソッドを必ず呼ぶので、結果、Closeメソッドは基本的に不要ということです。

しかし、1つ異なる点があります。

**Closeメソッドは再度そのインスタンスを再Openできるのに、対し、Disposeメソッドは一度実行されたら、そのインスタンスにはアクセスできない**

という点です。したがって「はじめに結論」での結論となります。


## ではなぜCloseを書くのか

[こちらの記事](https://stackoverflow.com/a/7525134/7510273)によると

> It doesn't affect the behaviour of the code, but it does aid readability.

つまり、 **可読性のため。(既存のコードに影響を与えないし)** とのこと。複数のスコープがあるとどこでインスタンスがCloseされているのかがわかりにくくなるので、Closeを書くとよいということです。

# おわりに

この記事の内容だけでは細かい理由が不十分だと思っています。追記するべき内容がわかったら適宜更新したいです。

# 補足

## StreamReaderクラスについて

StreamReaderにも、Closeメソッドが用意されていますが、(Componentクラスを継承している)DbConnectionとは様子が違ってくるようです。[こちらのQiitaの記事](http://qiita.com/iiokazuya/items/dfa0b66898a2b39fc1e9)に詳細と議論が展開されています。

## IDisposableインターフェースの実装

DbConnectionクラスはComponentクラスを継承しており、ComponentクラスでのDisposeメソッドでリソース管理の実装が記述されています。

独自にIDisposableインターフェースを実装したクラスを作成する必要があるとき、Disposeメソッドには、同様にリソース管理処理を実装する必要があります。

[こちらの公式ドキュメント](https://msdn.microsoft.com/ja-jp/library/system.idisposable.dispose(v=vs.110).aspx#Anchor_2)に具体的な実装方法が示されています。

この実装では、扱うリソースがGCの管理下かそうでないかを考慮して記述する必要があります。

# 参考

* MS公式ドキュメント
  * [using ステートメント (C# リファレンス)](https://msdn.microsoft.com/ja-jp/library/yh598w02(v=vs.110).aspx)
  * [DbConnection.Close メソッド ()](https://msdn.microsoft.com/ja-jp/library/system.data.common.dbconnection.close(v=vs.110).aspx)
  * [IDisposable.Dispose メソッド ()](https://msdn.microsoft.com/ja-jp/library/system.idisposable.dispose(v=vs.110).aspx#Anchor_2)
* Stack Overflow
  * [Should I call Close() or Dispose() for stream objects?](https://stackoverflow.com/a/7525134/7510273)
  * [in a “using” block is a SqlConnection closed on return or exception?](https://stackoverflow.com/questions/4717789/in-a-using-block-is-a-sqlconnection-closed-on-return-or-exception)
* Qiita
  * [StreamReader.Close()を呼ばなくていい理由](http://qiita.com/iiokazuya/items/dfa0b66898a2b39fc1e9)