C#のリソース解放にはIDisposableとusingを使おう

C#にはガーベッジコレクション (GC) という仕組みがあり、使われなくなったオブジェクトを自動的に破棄してくれるおかげで、メモリの解放し忘れによるメモリリークといった煩わしい問題を解決してくれます。

 

とは言え、GC は GC が考える良きタイミングで解放処理を始めます。

自分が必要とするタイミングで解放処理を始めてくれるとは限りません。

(例えばファイルのオープン・クローズを繰り返す場合、クローズされてからでないと次のオープンができません)

 

明示的にリソースを解放する手段 (メソッド) はやはり必要です。

IDisposable インターフェース

IDisposable インターフェースは「使用後はリソース開放が必要」ということを表しています。

 

IDisposable インターフェースはDispose()というメソッドを1つだけ持っており、

IDisposable インターフェースを実装するクラスは、このDispose()メソッド内でリソースの解放処理を行います。

 

 

標準のクラスライブラリでリソース解放が必要なクラスは IDisposable インターフェースを持っています。このようなクラスを使う場合は使い終わったタイミングで Dispose() メソッドを呼ぶようにしましょう。

            var sr = new StreamReader("text.csv");
            try
            {
                // 何かしらの処理
            }
            finally
            {
                sr.Dispose();
            }

例外が発生した場合でも確実に解放処理が行われるように finallyDispose() を呼ぶのが重要です。

using 構文

C#には Dispose() を自動で呼び出してくれる便利な using 構文というものがあります。

using のスコープから離れた(usingの{}から出た)時に自動的に Dispose() を呼び出してくれます。

もちろん例外が起きた場合にも対応しています。

 

以下のコードは上で書いた try ~ finally を使ったコードと同じように動作します。

            using (var sr = new StreamReader("text.csv"))
            {
                // 何かしらの処理
            }

IDisposable インターフェースを持つ複数のオブジェクトを使う場合、以下のように using を入れ子にして使う事も出来ます。

    try
    {
        using (var sw = new StreamWriter("out.csv"))
        {
            using (var sr = new StreamReader("in.csv"))
            {
                // 何かしらの処理
            }
        }
    }
    catch (Exception e)
    {
        // 例外処理
    }