• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:using文の使い方について)

using文の使い方について

このQ&Aのポイント
  • visual C# 2010 Expressを使用している場合、データベースのコネクションを取得するメソッドを作成することができます。
  • 生成したMySqlConnectionは適切に開放されているため、メモリリークの心配はありません。
  • 上記のコードは、データベースから値を取得するシンプルな例です。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

IDisposable.Disposeは,大元はUnmanaged Resource, つまりは.NET Frameworkが管理しないリソース, ぶっちゃければメモリ以外のリソースの統一した解放手段を提供するための物です。 で,IDisposable自体は自分できっちり実装する必要があります。 class Class1 : IDisposable { private bool _disposed = false; private int _i = 2; ~class1 () { Dispose(false); } public int { get { if (_disposed) throw new ObjectDisposedException(); // 破棄されたオブジェクト return _i; } set { if (_disposed) throw new ObjectDisposedExecption(); _i = value; } } protected virtual void Dispose (bool disposing) { if (_disposed) return; // 多重Disposeしても安全であること if (disposing) { // フィールドにあるIDisposableの解放等 } _disposed = true; } public void Dispose () { Dispose(true); GC.SuppressFinalize(this); // ファイナライザの呼び出しを抑制する } } で,本題ですが,トランザクションとかが関係しないのであれば, Queryメソッドでコネクションを開き,DataSetなりにデータを読んで,コネクションを閉じるまでしてしまいます。 IDisposableなオブジェクトは,他のオブジェクト以上に所有権を考えないといけないため, できるだけIDisposableなオブジェクトはusingで囲っておきたいです。 ASP.NETだとまた別の解があって, HttpContext.Current.ApplicationInstance.EndRequestイベントで解放するように構築してしまう,というのも手です。 ASP.NETだと短い時間で処理が終わるので,終了イベントを捕まえてそこで解放しても十分,という判断です。 # 実際にこういう作りにしたことがあります。

takagoo100
質問者

お礼

ご回答ありがとうございます。 なるほど、自分のやり方ではちゃんと実装してなかったわけですね・・・ 参考になりました。 やはりそうですか、usingで囲うしかないですかね。。 というより、考え方を変えて設計する必要がありそうですね。 これからも自分なりに作っていきたいと思います。

その他の回答 (1)

回答No.1

個人的には,「えっ,これで動くの?」という感じですが……。 using文は,そのブロックから出たタイミングでオブジェクトをDisposeします。 このため,GetConnectionメソッドの戻り値は「破棄されたオブジェクト」になり, 本来はOpenメソッドがObjectDisposedExceptionを発生させなければなりません。 書き換えるなら,こうでしょうか。 class Program { static void Main(string[] args) { using (MySqlConnection conn = GetConnection()) using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM tbl where id = '1'", conn)) { conn.Open(); using (reader = cmd.ExecuteReader()) // IDataReaderはIDisposableなのでDisposeを呼ぶ必要がある { reader.Read(); int i = reader.GetInt32(reader.GetOrdinal("id")); Console.WriteLine(i.ToString()); } // ここでreaderが解放される conn.Close(); // 書いた方が行儀が良いが,省略可能 } // ここでcmdとconnが解放される Console.ReadLine(); } static MySqlConnection GetConnection() { const string connStr = "server=localhost;Database=test;Uid=root;Pwd="; // constを付けておくと,変更不可能になる return new MySql.Data.MySqlClient.MySqlConnection(connStr); } }

takagoo100
質問者

お礼

ご回答ありがとうございます。 これは今も試しましたが確かに取得できるのです。。 自分的にはもちろんなぜだかは分からないのですが、 最初はシンプルなIDisposableを継承した class class1 : IDisposable { public int i = 2; public void Dispose() { Console.WriteLine("Dispose"); Console.ReadLine(); } } でGetConnection()のような使い方を試してみたのですが、これも値が変化しました。 もしお手数でなければ、Yune-Kichiさんの環境でも試してみて頂けないでしょうか? そして、提示して頂いたコードですが なるほど、たしかにこのやり方ならMySqlConnectionを GetConnectionに収めることができますね。 そもそもなんでこんなことを考えたかというと、 これも先ほどのPHPのフレームワークじゃないですけど 例えばzend frameworkのZend_Dbというクラスを使えば http://framework.zend.com/manual/ja/zend.db.adapter.html $db = Zend_Db::factory('Pdo_Mysql', $params); $db->query(); 一度$dbを作ってしまえば、あとはそれを使ってシンプル(?)な 記述で便利というか、でもそれは言語の固有の特性で 解放を自動的に行ってくれるので、このようなやり方が可能なのだと思います。 C#では当然ながら自動的に解放しないのでusingの中で処理を記述せざるえないわけですよね? 自分的にはなんとかzend frameworkじゃないですけど、それに近いクラスを C#でも作りたい(というか慣れ親しんだイメージのまま利用したい)と思ってて、 でも言語的にさっきのオブジェクトの解放もそうですけど、 クラスやメソッドの構成に影響を与える違いもでてくるので、どうしようか悩んでいるとろこです(う~ん、うまく説明できず申し訳ないです・・・) ちょっと漠然としすぎる質問で申し訳ないですが、もしYune-KichiさんがC#でデータベース関連のライブラリを 作成というかラップするようなクラスを作るとしたらどのように作りますか?先ほどの解放の問題も含めてですが

関連するQ&A