DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

Dispose、Closeが確実に呼び出されるようにする

このサイトの.NET Tipsでは、分かりやすさを優先しているため、紹介している多くのコードで例外処理を省略しています。特にDispose、Closeメソッドを確実に呼び出さなければならないケースで問題となる可能性があります。

まずは次のコードをご覧ください。これは、シフトJISのテキストファイルを読み込むコードです(詳しくは、こちらで説明しています)。

VB.NET
コードを隠すコードを選択
Dim sr As New System.IO.StreamReader("C:\test.txt", _
    System.Text.Encoding.GetEncoding(932))
Dim s As String =  sr.ReadToEnd() 
sr.Close()

Console.WriteLine(s)
C#
コードを隠すコードを選択
System.IO.StreamReader sr =
    new System.IO.StreamReader(@"C:\test.txt",
        System.Text.Encoding.GetEncoding(932));
string s = sr.ReadToEnd();
sr.Close();

Console.WriteLine(s);

上記のコードには問題があります。ReadToEndメソッドに失敗して例外がスローされた場合、Closeメソッドが呼び出されません。Closeメソッドはデータをファイルに書き込み、ファイルのロックを解除し、リソースを解放するために呼び出される必要があります。StreamReaderオブジェクトをこれ以上使用しないのであれば、Closeメソッドを呼び出すべきです。

このように、使用後にCloseやDisposeメソッドを呼び出す必要があるクラスは多く存在します(詳しくは、MSDNでご確認ください)。ここでは、確実にCloseやDisposeメソッドを呼び出す方法を紹介します。

try...finallyを使う方法

まずはtry...finallyステートメントを使用する方法を紹介します。上記のコードを書き換えてCloseメソッドが確実に呼び出されるようにするには、次のようにします。finallyステートメントにCloseメソッドを記述します。

VB.NET
コードを隠すコードを選択
Dim sr As System.IO.StreamReader = Nothing
Try
    sr = New System.IO.StreamReader( _
        "C:\test.txt", System.Text.Encoding.GetEncoding(932))
    Dim s As String = sr.ReadToEnd()
    Console.WriteLine(s)
Finally
    If Not (sr Is Nothing) Then
        sr.Close()
    End If
End Try
C#
コードを隠すコードを選択
System.IO.StreamReader sr = null;
try
{
    sr = new System.IO.StreamReader(@"C:\test.txt",
        System.Text.Encoding.GetEncoding(932));
    string s = sr.ReadToEnd();
    Console.WriteLine(s);
}
finally
{
    if (sr != null)
        sr.Close();
}

usingステートメントを使う方法

C#を使用しているか、.NET Framework 2.0以降であれば、usingステートメントを使用することができます。ほとんどのケースで、この方法の方がよりシンプルです。ただし、.NET Framework 1.1以前でVB.NETを使用しているならば、この方法は不可です。usingステートメントでは、IDisposeインターフェイスが実装されているクラスのDisposeメソッドが呼び出されることを保障します。

VB.NET
コードを隠すコードを選択
Dim s As String
Using sr As New System.IO.StreamReader( _
        "C:\test.txt", System.Text.Encoding.GetEncoding(932))
    s = sr.ReadToEnd()
End Using

Console.WriteLine(s)
C#
コードを隠すコードを選択
string s = "";
using (System.IO.StreamReader sr =
    new System.IO.StreamReader(@"C:\test.txt",
        System.Text.Encoding.GetEncoding(932)))
{
    s = sr.ReadToEnd();
}

Console.WriteLine(s);

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。