[C#] usingの意味と使い方 自動リソース解放機能(close、disposeを)

シェアする

  • このエントリーをはてなブックマークに追加

私のようにJava上がりのプログラマーが、初めてC#のusingステートメントを見ると「何これ?」という感じです。

ただ、実際にC#のusingの概念を知って使ってみると、とても便利に感じます。

これぞ、長年プログラムを実装してきて、どんなバグが起こるかを知りきっている人が、未然にバグを防ぐ仕組みを実装したかの印象を受けます。

usingを一言で説明すると、usingを使ってプログラムでリソースをオープンした場合、usingのスコープを抜けると自動的に確保したリソースを解放してくれます。

ここでリソースとは、ファイルへのアクセスとかデータベースのアクセスなど、プログラム外のリソースに対してアクセスする手段を確保する何らかのメモリのことです。

usingの仕事は、単純なのですが、プログラムのエラーケースを考えると、バグの発生をおさえてくれる、とても便利な機能と分かります。

usingがどれだけ便利か、ちょっと例を見てみましょう。

スポンサードリンク

FileStreamとStreamReaderでファイルをオープンして表示するサンプル

これは、FormにButtonとTextBoxとOpenFileDialogを貼っただけのとても簡単なプログラムです。

image

ボタンクリックに以下の機能を実装します。

単純にテキストファイルをオープンして、TextBoxに表示するプログラムです。

一見、正しく動作しそうです。

ただ、1つのファイルをオープンした後、再度、同じファイルをオープンすると以下のエラーが発生します。

GW-02765

 

型 'System.IO.IOException' の初回例外が mscorlib.dll で発生しました

追加情報: 別のプロセスで使用されているため、プロセスはファイル 'C:\Users\xxxx\Documents\aaa.txt' にアクセスできません。

この例外のハンドラーがある場合は、プログラムを安全に続行できます。

そこで、プログラムの最後に以下の行を追加しました。

これで、一応エラーを回避することが出来ます。

スポンサードリンク

FileStreamとStreamReaderを明示的にcloseするサンプル

もう少し実用的な例を考えてみましょう。

実際に実用されるプログラムでは、様々な処理が入ってきますし、プログラムの処理の途中で例外が発生する事がよくあります。

そこで下記では、わざと例外を発生させて、実用的なプログラムを模してみました。

GW-02766

型 'System.Exception' のハンドルされていない例外が UsingSample.exe で発生しました

追加情報: Exception

(上記のダイアログのExcepionはスペルミスです。マイクロソフトの人、気づかないかなぁ。)

Exceptionをハンドルしていないので、このようなエラーが発生してしまいます。

そこで、Exceptionをcatchしたプログラムに変更してみます。

一見、プログラムは正しそうなので実行してみます。

以下のExceptionが発生しました。

要はsrはNULLのままなので、sr.Close()が実行できないわけです。

GW-02767

型 'System.NullReferenceException' のハンドルされていない例外が UsingSample.exe で発生しました

追加情報: オブジェクト参照がオブジェクト インスタンスに設定されていません。

このエラーの回避方法として、単純に考えると以下のようになります。

2個のリソースのnullチェックなら、問題ないかもしれませんが、これがもっと沢山のリソースを使った場合はどうでしょうか。

Exceptionをcatchしたところで、nullになる可能性があるリソースをすべてnullチェックしていくのは、賢くないし、バグを引き起こす可能性を生み出しますね。

そこで、真打ち、usingの登場です。

スポンサードリンク

usingを使ってFileStreamとStreamReaderを確実にcloseするサンプル

以下が、usingを使ったサンプルプログラムです。

当然ながら、 throw new Exception("Exception")をコメントアウトしても動作します。

このプログラムの注目すべき点は、リソースのcloseもdisposeもしないし、nullチェックもしなくてよい、っていうことです。

using()でインスタンス化されたオブジェクトは、usingに続く{}を抜けると必ず解放されます。

これはとても便利です。

usingステートメント実装方法

usingを使ってインスタンス化するオブジェクトは、IDiposableインターフェースを実装したものに限ります。

IDisposableインターフェースを実装すると、必ず、IDisposable.Dispose()メソッドがコールされるために、インスタンスが確実に解放されるわけです。

標準関数なら、問題ないので、usingをとにかく使いましょう。

usingは文字通り、使っているっていう意味なので、using(xxx){}となっていれば、{}の中ではxxxを使っている。{}を出れば、xxxを使っていない、って考えれば分かりやすいです。

お役に立ちましたら、シェアをお願いします。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です