Last-modified: 2003-12-21 (日) 15:18:06 (7426d)

 DBコネクションやファイルストリーム等、排他制御の対象となる資源を制御するオブジェクトのインスタンスを確実に開放したい場合、Javaだったら、try...finally構文 を使いますよね?

try {
  Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/eg");
  String sql = "SELECT * FROM User"
             + " WHERE username = ?"
             + " AND password = ?";
  PreparedStatement pstmt = conn.prepareStatement(sql);
  pstmt.setString(1, uname);
  pstmt.setString(2, passwd);
  ResultSet rs = pstmt.executeQuery();

  if (rs.next())
    System.out.println("The User Exists !!!");
} catch (Exception e) {
    System.err.println("なんらかのえら~", e);
} finally {
  try {
    if (rs != null) { rs.close(); }
    if (pstmt!= null) { pstmt.close(); }
    if (conn != null) { conn.close(); }
  } catch (SQLException sqle) {
    System.err.println("DB接続を切断できない?", sqle);
  }
}

 C#でも同様なコードが書けます。

public static void Function (string strFilename)
{
  StreamWriter stream = new StreamWriter (strFilename, false, System.Text.Encoding.Default);
  try
  {
    stream.WriteLine("こんにちは!世界");
  }
  finally
  {
    stream.Close ();
  }
}

 こういうtry...finally構文は頻繁に利用されますので
、C#では同じ働きをする using構文が用意されています。上のプログラムとほぼ同じ動作をするプログラムが以下のように簡略に記述できます。

public static void Function (string strFilename)
{
  using (StreamWriter stream = new StreamWriter (strFilename, false, System.Text.Encoding.Default))
  {
    stream.WriteLine("こんにちは!世界");
  }
}

 上記の2種のコードは実は微妙に動作が異なります。前者は stream.Close() を呼び出していますが、usingを用いた後者は stream.Dispose() が呼び出されます。
 逆に言えば、リソースを開放する必要のあるようなクラスは IDisposable を実装しています。「終了メソッドは何だっけ?」と悩むことなく、とにかく Dispose() を呼べばOKなのです。

※ クラスリファレンスには Dispose() メソッドが記載されていないことが多いです。親クラスからの継承が多いからかな?

 また、using構文はネストも可能です。using構文のネストは、using()をまとめて書くと2つ目以降の{}を省略することができます。

using(.......)
using(......)
{
}

 資源の解放を確実に行いたいケースでは、原則としてusing構文を使うようにするとよいでしょう。


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS