using ステートメント (C# リファレンス)
using
ステートメントは、IDisposable オブジェクトの正しい使用を保証する簡易構文を提供します。 await using
ステートメントによって IAsyncDisposable オブジェクトが適切に使用されるようになります。 この言語では、System.IAsyncDisposable インターフェイスを実装する非同期の破棄可能な型がサポートされます。
例
using
ステートメントを使用する方法の例を次に示します。
string manyLines = @"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";
using (var reader = new StringReader(manyLines))
{
string? item;
do
{
item = reader.ReadLine();
Console.WriteLine(item);
} while (item != null);
}
"using 宣言" に中括弧は不要です。
string manyLines = @"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";
using var reader = new StringReader(manyLines);
string? item;
do
{
item = reader.ReadLine();
Console.WriteLine(item);
} while (item != null);
Remarks
File と Font は、アンマネージド リソース (この場合はファイル ハンドルとデバイス コンテキスト) にアクセスするマネージド型の例です。 アンマネージ リソースや、それをカプセル化するクラス ライブラリ型は他にもたくさんあります。 このようなすべての型は、IDisposable インターフェイスまたは IAsyncDisposable インターフェイスを実装する必要があります。
IDisposable
オブジェクトの有効期間が 1 つのメソッドに限定されているとき、それを using
ステートメントまたは using
宣言で宣言し、インスタンス化してください。 using
宣言では、範囲から外れたとき、正しい方法で、オブジェクト上で Dispose メソッドが呼び出されます。 using
ステートメントでは、Dispose が呼び出された直後、オブジェクト自体が範囲から外れます。 オブジェクトは、using
ブロック内では読み取り専用です。変更したり再割り当てしたりすることはできません。 using
宣言で宣言された変数は読み取り専用です。 オブジェクトに IDisposable
ではなく IAsyncDisposable
が実装されている場合、いずれかの using
フォームから DisposeAsync が呼び出され、返される ValueTask の awaits
を行います。 IAsyncDisposable の詳細については、「IAsyncDisposable」を参照してください。
両方の using
フォームにより、using
ブロック内で例外が発生した場合でも必ず Dispose (または DisposeAsync) が呼び出されます。 オブジェクトを try
ブロックに配置し、finally
ブロック内で Dispose (または DisposeAsync) を呼び出しても、同じ結果が得られます。実際には、コンパイラによって using
ステートメントと using
宣言がこのように変換されます。 前のコード例は、コンパイル時に次のコードに展開されます (オブジェクトのスコープ制限を定義する中かっこが加えられていることに注意してください)。
string manyLines = @"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";
{
var reader = new StringReader(manyLines);
try
{
string? item;
do
{
item = reader.ReadLine();
Console.WriteLine(item);
} while (item != null);
}
finally
{
reader?.Dispose();
}
}
新しい using
ステートメントの構文は似たコードに変換されます。 変数が宣言されている場所で try
ブロックが開きます。 finally
ブロックは、囲んでいるブロックの終わり、通常はメソッドの最後に追加されます。
try
-finally
ステートメントの詳細については、「try
」の記事を参照してください。
次の例のように、1 つの using
ステートメントで型の複数のインスタンスを宣言できます。 1 つのステートメントで複数の変数を宣言する場合、暗黙的に型指定された変数 (var
) を使用できないことに注意してください。
string numbers = @"One
Two
Three
Four.";
string letters = @"A
B
C
D.";
using (StringReader left = new StringReader(numbers),
right = new StringReader(letters))
{
string? item;
do
{
item = left.ReadLine();
Console.Write(item);
Console.Write(" ");
item = right.ReadLine();
Console.WriteLine(item);
} while (item != null);
}
次の例に示すように、宣言構文を使用し、同じ型の複数の宣言を組み合わせることができます。
string numbers = @"One
Two
Three
Four.";
string letters = @"A
B
C
D.";
using StringReader left = new StringReader(numbers),
right = new StringReader(letters);
string? item;
do
{
item = left.ReadLine();
Console.Write(item);
Console.Write(" ");
item = right.ReadLine();
Console.WriteLine(item);
} while (item != null);
リソース オブジェクトをインスタンス化してから、変数を using
ステートメントに渡すことはできますが、これはベスト プラクティスではありません。 この場合、アンマネージド リソースへのアクセスがなくなっている可能性が高いのにもかかわらず、制御が using
ブロックを離れた後もオブジェクトはスコープ内に残ります。 つまり、完全に初期化されることはなくなります。 using
ブロックの外側でオブジェクトを使用しようとすると、例外がスローされる可能性があります。 このため、オブジェクトを using
ステートメントでインスタンス化して、そのスコープを using
ブロックに制限することをお勧めします。
string manyLines = @"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";
var reader = new StringReader(manyLines);
using (reader)
{
string? item;
do
{
item = reader.ReadLine();
Console.WriteLine(item);
} while (item != null);
}
// reader is in scope here, but has been disposed
IDisposable
オブジェクトの破棄に関する詳細については、「IDisposable
」を参照してください。
C# 言語仕様
詳細については、C# 言語仕様に関するページの using ステートメントに関するセクションを参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。