using var宣言でリソースを解放しよう

using varによる宣言がC#にはありますが、見かけたことはありますか。

今回はusing varの役割と利用するメリットについて紹介します。

プログラムの外と連携するような場合、using varは強力な記述です。

データベースやファイルアクセスなどを書く予定の方は
using varの機能が役に立つはずです。

using var宣言は自動でリソースを破棄する仕組みのひとつ

using varとはメモリの解放の仕組みです。


ちなみにここでいうusing varのvarは型の宣言なので、varではなく明確な型指定もできます。
上記の例でいうと、using FileStreamともできます。

  • C#は基本的にメモリを意識しなくて問題ない
  • C#で自動でメモリ解放しないものもある

では、using varがメモリとどのように関わるのか見てみましょう。

C#は基本的にメモリを意識しなくて問題ない

基本的にC#はメモリを管理する必要がありません。

オブジェクトを作った後は、自分で破棄せずとも
いつの間にかメモリから解放されていたりします。

メモリの消費はいつの間にかなくなっているため、
自分たちで意識する機会はすくないでしょう。

C#で自動でメモリ解放しないものもある

しかしながら、C#にはメモリを管理しなければならないオブジェクトの存在があります。

それが冒頭でもふれた、プログラムの外と連携する場合などです。

データベースへのアクセスやファイル操作では、
using var を利用してメモリを解放してあげる必要があります。

余談ですが、このusing はC#コードファイル(.cs)の一番上にある
「using System.Text;」のusingとは、特に関係はないです。

using varで宣言可能なものの特徴

外部リソースを使うものはが何かわかれば、問題はありません。

しかし、プログラムを始めたばかりでは、どこまでがプログラムの境界かわからないこともあります。

using varを利用できるオブジェクトの特徴を紹介します。

using var で解放するにはDisponseメソッドが必要

using varによるリソース解放は、裏でDisposeメソッドが呼ばれることで行われます。

つまり、using varが使えるオブジェクトの見分けるポイントは、Disponseメソッドがあるかどうか、
より正確に述べると、IDisposableの実装があるかで確認できます。

IDisposableが実装されている例はこんな感じ、


データベースにアクセスするための仕組み、
Entity frameworkのオブジェクトです。

IDisposableをもち、Disposeメソッドが実装が確認できますね。
このようなオブジェクトであれば、using varを使用できると考えてOKです。

using var を使わないと最悪プログラムが止まる

using varを付けるべきオブジェクトに、うっかりusing varをつけ忘れるとどうなるのでしょうか。

極端な言い方をするとプログラムが止まります。

プログラムを動かすためのメモリを使い切って、OutOfMemoryExceptionが発生する可能性が、ひとつ考えられます。

長時間動かすプログラムや大量の処理をおこなうプログラムは注意したほうがよいです。

また、外部のリソースをロックする可能性もあります。

外部リソースを占有し続けてしまうと、
別のプログラムが利用できないなどの問題も引き起こします。

ファイル操作やトランザクションで発生しやすいです。

このような問題を避けるためにも、using varで適切にリソースを解放しましょう。

using var で書くとシンプルになる

実際のところ、using varを使わなくてもリソースを破棄する方法はあります

ただ、using varを使うより記述が増えてしまうため、
ちょっとメンドクサイことをしないといけないです。

では using varを使う場合と使わない場合を見ていきましょう。

まずは使わない場合、


自分でDisponseメソッドを呼ぶ方法です。

Try/Finallyで対応できます。

つづいてusing varの場合を改めて確認。


Finallyが無くなりましたね。

using varを使うと、Disponseメソッドを記載なしでリソースを
解放してくれるため、その分シンプルなコードになります。

なぜ、全部自動で解放してくれないのか

そもそも何故外部リソースを解放してくれないのでしょうか。

Disponseメソッドがあるものは、プログラム側で勝手にメモリを解放してくれてもいいように感じるかもしれません。

その理由は、外部リソースにアクセスする場合でメモリを解放しないほうがよいパターンがあるからです。

言い換えると、自分たちでメモリを解放するかコードで決められるようにusing var が用意されているといえます

一回一回破棄したほうが良いのか、逆に破棄しないほうが良いのか、
具体例を見ていきましょう。

using varを使ってはいけない外部との通信の例

外部リソースにアクセスしていてもusing varを使わないほうが良い例があります。

大量のアクセスをサバくために破棄しない例「HttpClient」です。

WEBリソースという外部リソースにアクセスする代表みたいなオブジェクトですけれども、
公式ドキュメントにおいてusing varを使わないことを奨励しています。

HttpClient は、1回インスタンス化し、アプリケーションの有効期間全体に再利用することを目的としています。 すべての要求に対して HttpClient クラスをインスタンス化すると、大量の読み込みで使用可能なソケットの数が枯渇します。 これにより、SocketException エラーが発生します。

要は、「同じようなアドレスにアクセスする場合はHttpClientを使いまわしてね」ということです。

一度使ったリソースを使いまわすことで、リソースを過剰に消費しないようにしています。
いわば、リソースを解放することでリソース消費を抑えるという考え方と真逆です。

大量にアクセスしないのであれば、リソース解放しても問題ないのかもしれませんが、
公式のドキュメントに従ったほうが無難でしょう。

外部リソースにアクセスするオブジェクトであっても、
using varを使わないパターンがある
ということは、心に留めておきたいところです。

using var を使うほうが良い例

続いてusing var などを利用したほうがよい例です。

前段でもふれましたが、ファイル操作やトランザクションなどのデータベース操作は要注意です。

適切に解放しないと、リソースのロックを誘発することをお伝えしました。

さらにここで「自動でリソース解放されるとなるとどうなるか」も考えてみましょう。

データベースに接続している途中・SQLコマンドの途中・トランザクションの途中、
どれも途中でリソースが解放されると困りますね。

データベースアクセスに関連するトランザクションを使ったままにしてしまっては
データベース全体に影響がでますし、

一方でかってにトランザクションが破棄されては、目的の操作が失敗してしまいます。

自分たちでリソース利用の開始と終了をコントロールすることこそ、using varを使うひとつの理由です。

ひとつひとつ特性にあった破棄をしよう

全部にusing var宣言をするわけではないこと、
そして自分たちで破棄のタイミングを決めたい例を紹介しました。

外部リソースの利用方法によってい特徴がありましたね。

使う道具はどんな動きをするか確認してから使うほうが安全でしょう。

利用するオブジェクトごとにusing varを使う・使わないを判断していかなければならないので、
難しい部分ではありますが、ある意味では、プログラムを組むうえでの腕の見せ所とも言えます。

Disponseメソッドを見かけたら、どのように扱うのがベストか
立ち止まって考えたいですね。

まとめ

  • using var宣言で外部リソースと連携するオブジェクトを破棄できる
  • IDisposable/Disponseメソッドはusing varで制御できる
  • 外部リソースと連携するオブジェクトはそれぞれの特徴に合わせて破棄する

using varが何をしているのか、その意味について紹介しました。

外部リソースと連携する部分はバグやエラーが発生しやすい箇所ではありますが、
using varで回避できるものもあると思いますので、チャンスがあれば使ってみてください。

では。

カテゴリー: C#