外部リソースの解放には using ステートメントを使う

## 外部リソースは確実に破棄する

ファイルやデータベース、ネットワークなどの外部リソースを使用する .NET Framework のクラスは使い終わったら `Dispose()` メソッドを呼び出してリソースを開放する必要があります。
`Dispose`を忘れるとファイルがオープンしたままになって他から利用できなくなったり、メモリリークが発生したりする危険があるため確実に `Dispose()` する必要があります。

```c#:finallyで確実にDisposeする
var reader = new StreamReader(@"Sample.txt");
try
{
    string text = reader.ReadToEnd();
    Console.WriteLine(text);
}
finally
{
    reader.Dispose();
}
```

上記のように `finally` ブロックで確実に `Dispose()` を呼び出すこともできますが、
`using ステートメント` を使うともっと簡潔にスマートにコーディングできます。
（≠ 名前空間をインクルードする `using ディレクティブ`）

```c#:usingステートメントを使ったリソースの破棄
using (var reader = new StreamReader(@"sample.txt"))
{
    string text = reader.ReadToEnd();
    Console.WriteLine(text);
}
```

`using` のブロック `{}` を抜けた際に自動で `reader.Dispose()` が呼ばれます。
名前も `using` なので `try {...} finally {...}` より意図が明確です。
また、万が一 `Dispose()` を忘れてしまったり、消してしまうこともなくなります。

## 確実に `Dispose()` が呼ばれる

`finally` と同様に例外がスローされようが途中でリターンされようが `{}` を抜ける際に必ず `Dispose()` が呼ばれます。
（IL（.NET Framework の中間言語）を見ると `try {...} finally {...}` が生成されているようです。）

```c#:ブロック内でreturnしてもDisposeされる
string GetText(string path)
{
    using (var reader = new StreamReader(path))
    {
        string text = reader.ReadToEnd();
        return text;
    }
}
```

## リソースオブジェクトを複数同時に宣言する

同じ型の場合、リソースオブジェクトは１つの `using` で複数同時に宣言することができます。
区切りには `,` を使用します。
この場合、型推論 `var` は使用することはできません。

```c#:リソースオブジェクトを複数同時に宣言する
using (StreamReader // var は不可
    reader1 = new StreamReader(@"Sample1.txt"),
    reader2 = new StreamReader(@"Sample2.txt"),
    reader3 = new StreamReader(@"Sample3.txt"))
{
    // 外部リソースを使った処理
}
```

## 複数の `using` を多段重ねできる

ネストを作らず多段重ねすることができます。
一つ目の `using` の末尾には `;` も `{` もついていません。

```c#:多段重ねされたusing
using (var reader = new StreamReader(@"Sample1.txt"))
using (var writer = new StreamWriter(@"sample2.txt"))
{
    // 外部路ソースを使った処理
}
```

## 注意点

以下のように、リソースオブジェクトをインスタンス化してから `using` ステートメントに渡すこともできますがこれは推奨されていません。
外部リソースへのアクセスがなくなっている可能性が高いですが、変数のスコープが残ってしまいます。
リソースオブジェクトの宣言は `using` ステートメント内で行うことが推奨されています。

```c#:例外が発生する可能性の高いコード
var reader = new StreamReader(@"Sample.txt");
using (reader)
{
    // reader を使った処理
}
// reader はスコープ内だが、
// 外部リソースへのアクセスが失われている可能性があり、
// 例外がスローされる場合がある
string line = reader.ReadLine();
```

また、`using` を使用するリソースオブジェクトは `IDisposable` インターフェースの `Dispose` メソッドを実装している必要があります。
と言っても、 .NET Framework の外部リソースを扱うクラスは `IDisposable` が実装されているので特に気にする必要はありません。
自作する場合でも Visual Studio では リファクタリング機能 `ctrl + .` で一瞬でスケルトンコードが生成できるのでそれほど面倒ではないはず。

```c#:
class MyDisposableClass : IDisposable
{
    // 以下自動生成されたコード
    #region IDisposable Support
    private bool disposedValue = false; // 重複する呼び出しを検出するには

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: マネージ状態を破棄します (マネージ オブジェクト)。
            }

            // TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下のファイナライザーをオーバーライドします。
            // TODO: 大きなフィールドを null に設定します。

            disposedValue = true;
        }
    }

    // TODO: 上の Dispose(bool disposing) にアンマネージ リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。
    // ~MyDisposableClass() {
    //   // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
    //   Dispose(false);
    // }

    // このコードは、破棄可能なパターンを正しく実装できるように追加されました。
    public void Dispose()
    {
        // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
        Dispose(true);
        // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。
        // GC.SuppressFinalize(this);
    }
    #endregion
}
```

ここまで読んでいただきありがとうございました。

## 参考

[using ステートメント (C# リファレンス)](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-statement)
[[C#]Usingを使え](http://anopara.net/2013/05/16/cusing%E3%82%92%E4%BD%BF%E3%81%88/)
[C# Tips －usingを使え、使えったら使え(^^)－](http://divakk.co.jp/aoyagi/csharp_tips_using.html)
[C#のusingステートメントの機能](http://takachan.hatenablog.com/entry/2017/09/10/223846)