using(名前空間インポート / リソース解放)(C#)
名前空間のインポートとリソースの自動解放という2つの役割を持つ『using』キーワードです。『C#』では using System; のように名前空間を取り込む宣言構文と、using (var r = ...) { } のようにオブジェクトを確実に破棄するステートメントの、まったく異なる2つの用途に同じキーワードを使います。
構文
// ① 名前空間のインポートです。ファイルの先頭に書きます。
using System;
using System.Collections.Generic;
// ② usingステートメントです。ブロックを抜けると自動でDispose()が呼ばれます。
using (var resource = new ResourceClass()) {
// リソースを使う処理
} // ← ここで resource.Dispose() が確実に呼ばれます。
// ③ using宣言(C# 8以降)です。スコープを抜けたときにDisposeされます。
using var resource = new ResourceClass();
// ブロック終端で自動Dispose(ブレースなしで書けます)。
// ④ global using(C# 10以降)です。プロジェクト全体で有効になります。
global using System;
global using System.Collections.Generic;
// ⑤ using staticです。静的メンバーをクラス名なしで直接呼び出せます。
using static System.Console;
using static System.Math;
// WriteLine("hello"); のように Console. を省略できます。
using の主な使い方一覧
| 構文 | 目的 | 備考 |
|---|---|---|
using 名前空間; | 名前空間のインポート | ファイル先頭に書く。対象ファイルのみ有効。 |
global using 名前空間; | プロジェクト全体へのインポート | C# 10以降。通常は専用ファイル(GlobalUsings.cs)にまとめる。 |
using static クラス名; | 静的メンバーの直接アクセス | Math.Abs → Abs のように省略できる。 |
using (var x = ...) { } | リソースの自動解放(ブロック形式) | IDisposable を実装したオブジェクトに使用。 |
using var x = ...; | リソースの自動解放(宣言形式) | C# 8以降。スコープ終端でDispose。 |
サンプルコード
UsingNamespace.cs
// --- ① 名前空間のインポート ---
// using を書かないと完全修飾名(System.Console.WriteLine など)が必要になります。
using System;
using System.Collections.Generic;
class UsingNamespace {
static void Main() {
// using System; があるため System.Console.WriteLine と書かなくて済みます。
Console.WriteLine("=== メンバー一覧 ===");
// using System.Collections.Generic; があるため List<T> を短く書けます。
List<string> members = new List<string> {
"member_01",
"member_02",
"member_03",
"member_04",
"member_05"
};
foreach (string name in members) {
Console.WriteLine(" " + name);
}
}
}
コンパイルして実行すると次のようになります。
dotnet script UsingNamespace.cs === メンバー一覧 === member_01 member_02 member_03 member_04 member_05
UsingStatic.cs
using System;
// --- ⑤ using static ---
// クラス名を省略して静的メンバーに直接アクセスできます。
using static System.Console;
using static System.Math;
class UsingStatic {
static void Main() {
// using static System.Console; により Console. を省略しています。
WriteLine("=== 数値計算 ===");
double baseEnergy = 1200.0;
// using static System.Math; により Math. を省略しています。
double amplified = Round(baseEnergy * 1.75, 2);
double maxEnergy = Max(amplified, 5000.0);
WriteLine("基礎値: " + baseEnergy);
WriteLine("強化後: " + amplified);
WriteLine("上限適用後: " + maxEnergy);
// PI も Math. なしで参照できます。
WriteLine("円の面積: " + Round(PI * 50 * 50, 2));
}
}
コンパイルして実行すると次のようになります。
dotnet script UsingStatic.cs === 数値計算 === 基礎値: 1200 強化後: 2100 上限適用後: 5000 円の面積: 7853.98
UsingStatement.cs
using System;
using System.IO;
class UsingStatement {
static void Main() {
// --- usingステートメント(ブロック形式)---
// StreamWriter は IDisposable を実装しているため using で確実に閉じられます。
// 例外が発生してもブロックを抜ける際に必ず Dispose() が呼ばれます。
string filePath = "output_log.txt";
using (StreamWriter writer = new StreamWriter(filePath)) {
// ブロック内でファイルに書き込みます。
writer.WriteLine("=== 処理記録 ===");
writer.WriteLine("task_01: completed");
writer.WriteLine("task_02: in_progress");
writer.WriteLine("task_03: completed");
} // ← ここで writer.Dispose() が呼ばれ、ファイルが確実に閉じられます。
Console.WriteLine("処理記録を書き込みました。");
// --- using宣言(C# 8以降、ブレースなし形式)---
// スコープ(メソッドの終端)で自動的に Dispose されます。
using StreamReader reader = new StreamReader(filePath);
string content = reader.ReadToEnd();
Console.WriteLine("\n--- ファイルの内容 ---");
Console.WriteLine(content);
// ← メソッド終端で reader.Dispose() が呼ばれます。
}
}
コンパイルして実行すると次のようになります。
dotnet script UsingStatement.cs 処理記録を書き込みました。 --- ファイルの内容 --- === 処理記録 === task_01: completed task_02: in_progress task_03: completed
UsingIDisposable.cs
using System;
// IDisposable を実装した独自クラスです。
// リソースを管理するクラスを例にします。
class ManagedResource : IDisposable {
private string fieldName;
private bool disposed = false;
public ManagedResource(string name) {
fieldName = name;
Console.WriteLine("[" + fieldName + "] リソース確保");
}
public void UseEnergy(string userName) {
// Disposeされた後に使おうとした場合は例外をスローします。
if (disposed) {
throw new ObjectDisposedException(fieldName, "すでにリソースが解放されています。");
}
Console.WriteLine("[" + fieldName + "] " + userName + " がリソースを使用しました。");
}
// IDisposable.Dispose() の実装です。
public void Dispose() {
if (!disposed) {
Console.WriteLine("[" + fieldName + "] リソース解放。");
disposed = true;
}
}
}
class UsingIDisposable {
static void Main() {
// using ブロックを抜けると自動で ManagedResource.Dispose() が呼ばれます。
using (ManagedResource field = new ManagedResource("resource_a")) {
field.UseEnergy("process_1");
field.UseEnergy("process_2");
} // ← ここで Dispose() が呼ばれ「リソース解放。」が表示されます。
Console.WriteLine();
// --- using宣言形式でも同じ結果になります ---
using ManagedResource field2 = new ManagedResource("resource_b");
field2.UseEnergy("process_3");
// メソッド終端で Dispose() が呼ばれます。
}
}
コンパイルして実行すると次のようになります。
dotnet script UsingIDisposable.cs [resource_a] リソース確保 [resource_a] process_1 がリソースを使用しました。 [resource_a] process_2 がリソースを使用しました。 [resource_a] リソース解放。 [resource_b] リソース確保 [resource_b] process_3 がリソースを使用しました。 [resource_b] リソース解放。
よくあるミス
IDisposable を実装していないオブジェクトに using を使う
using ステートメント / 宣言は IDisposable インターフェースを実装したオブジェクトにのみ使えます。実装していないクラスに対して using を書くとコンパイルエラーになります。
// using (string s = "hello") { }
using (StreamWriter w = new StreamWriter("log.txt")) {
w.WriteLine("ok");
}
using 宣言のスコープを誤解する
using var(C# 8 以降の宣言形式)は、変数が宣言されたスコープ(通常はメソッドの末尾)で Dispose() が呼ばれます。ブロック形式のように「すぐ閉じたい」場合は、明示的に using (...) { } のブロック形式を使ってください。
static void Example() {
// using 宣言形式: メソッド末尾まで Dispose されません。
using var writer = new StreamWriter("data.txt");
writer.WriteLine("data");
// ← ここではまだ Dispose されていません。
using (var writer2 = new StreamWriter("data2.txt")) {
writer2.WriteLine("data");
} // ← ここで即座に Dispose されます。
}
概要
『C#』の using キーワードには「名前空間のインポート」と「リソースの自動解放」という2つの役割があります。名前空間のインポートは完全修飾名を省略するための宣言で、ファイル先頭に書きます。C# 10以降の global using を使うと、プロジェクト内のすべてのファイルに対して一括でインポートを適用できるため、繰り返し書く手間を省けます。
リソースの自動解放では、IDisposable インターフェースを実装したオブジェクト(ファイル・ネットワーク接続・データベース接続など)を using で囲むと、ブロックを抜ける際に例外が発生しても必ず Dispose() が呼ばれます。これは try / finally で Dispose() を手動呼び出しするパターンと等価ですが、using を使う方が短く安全に書けます。C# 8以降の using var(using宣言)は波かっこなしで書ける形式で、変数のスコープ(メソッドの末尾)で自動的に解放されます。
using static はクラス名を省略して静的メンバーに直接アクセスする機能です。Console.WriteLine を WriteLine だけで呼び出せるなど、コードを短くできますが、どのクラスのメンバーかわかりにくくなる場合があるため使いすぎには注意が必要です。リソース解放の詳細は『try / catch / finally』も合わせて参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。