本文へスキップ
BecomeCoder

C#オブジェクト指向コース · 第5章 オブジェクト指向の実践テクニック · レッスン39

IDisposable と using パターン

ブラウザで完結

導入

ファイル・DB接続・ネットワークなど「使い終わったら閉じる必要がある資源」は、閉じ忘れると枯渇します。IDisposable は「後片付けの作法」を型に持たせるインターフェースで、using はそのブロックを抜けるときに必ず片付けを呼んでくれる構文です。

図解

flowchart LR
    U["using (var r = new Resource())"] --> B["ブロック内の処理"]
    B --> D["ブロックを抜けると自動で<br/>r.Dispose() が呼ばれる"]
    style D fill:#e8f5e9

サンプル

using (var r = new Resource("DB"))
{
    r.Use();
}   // ← ここで自動的に r.Dispose() が呼ばれる

// using 宣言(波かっこ省略)ならスコープの終わりで片付く
using var log = new Resource("Log");
log.Use();

class Resource : IDisposable
{
    private readonly string _name;
    public Resource(string name) { _name = name; Console.WriteLine($"{_name} を開いた"); }
    public void Use() => Console.WriteLine($"{_name} を使用");
    public void Dispose() => Console.WriteLine($"{_name} を閉じた");
}

出力:

DB を開いた
DB を使用
DB を閉じた
Log を開いた
Log を使用
Log を閉じた
  • IDisposableDispose() に後片付けを書く
  • using はブロック(またはスコープ)を抜けるとき、例外が起きても必ず Dispose() を呼ぶ
  • 資源を扱う型は基本 IDisposableusing で包むのが定石

やってみよう

using を外して new Resource("X").Use(); だけにすると「閉じた」が出ないことを確かめ、using の有無で後片付けが変わることを体感しましょう。

演習

// TODO: Dispose で "closed" を出力する IDisposable な Handle を定義し、using で使ってください
___

using (var h = new Handle())
{
    Console.WriteLine("working");
}
// 期待: working → closed の順で出力される
  • 期待される出力: working\nclosed
ヒント1を見る

class Handle : IDisposable { public void Dispose() => Console.WriteLine("closed"); }

ヒント2を見る

using ブロックを抜けると Dispose() が呼ばれるので、“working” の後に “closed” が出ます

まとめ

  • IDisposable は「後片付けの作法」を型に持たせる
  • using はスコープを抜けるとき必ず Dispose() を呼ぶ(例外時も)
  • 資源を扱う型は using で包むのが定石

次回: デザインパターンコースへ。再利用できる設計の「型」を学びます。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。