私は次のコードを持っています
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
dispose()
メソッドはusing
文中括弧の最後で呼び出されます}
よね? ステートメントreturn
の終了前なので 、オブジェクトは適切に破棄されますか? そこで何が起こるの?using
MemoryStream
私は次のコードを持っています
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
dispose()
メソッドはusing
文中括弧の最後で呼び出されます}
よね? ステートメントreturn
の終了前なので 、オブジェクトは適切に破棄されますか? そこで何が起こるの?using
MemoryStream
はい、Dispose
呼ばれます。実行がブロックのスコープを離れるとすぐに呼び出されusing
ます。これは、ブロックの実行の終了、return
ステートメント、または例外など、ブロックを離れるために必要な手段に関係なく行われます。
@Noldorinが正しく指摘しているように、コードでブロックを使用すると、ブロックで呼び出されて/にusing
コンパイルされます。たとえば、次のコード:try
finally
Dispose
finally
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
効果的に次のようになります。
MemoryStream ms = new MemoryStream();
try
{
// code
return 0;
}
finally
{
ms.Dispose();
}
したがって、finally
はブロックの実行が終了した後に実行されることが保証されているためtry
、その実行パスに関係なくDispose
、何があっても呼び出されることが保証されています。
詳細については、この MSDN 記事を参照してください。
補遺:
追加するちょっとした警告:Dispose
は呼び出されることが保証されているため、ほとんどのDispose
場合、 を実装するときに が例外をスローしないようにすることをお勧めしますIDisposable
。残念ながら、コア ライブラリには、 が呼び出されたときに特定の状況でスローするクラスがいくつかありDispose
ます。WCF サービス リファレンス / クライアント プロキシを見ています。Dispose
-- そして、それが発生した場合、元の例外が呼び出しによって生成された新しい例外のために飲み込まれてしまうため、元の例外が例外スタックのアンワインド中に呼び出された場合、元の例外を追跡することは非常に困難になる可能性がありDispose
ます。それは非常にイライラすることがあります。それとも、それはイライラするほど怒っていますか?2つのうちの1つ。多分両方。
using
ステートメントはtry ... finally
ブロックとまったく同じように動作するため、常にすべてのコード出口パスで実行されます。finally
ただし、ブロックが呼び出されない非常にまれでまれな状況の影響を受けると思います。私が覚えている 1 つの例は、バックグラウンド スレッドがアクティブな間にフォアグラウンド スレッドが終了した場合です。GC 以外のすべてのスレッドが一時停止され、finally
ブロックが実行されません。
明らかな編集: IDisposable オブジェクトを処理できるようにするロジックを除けば、それらは同じように動作します。
ボーナスコンテンツ:積み重ねることができます (種類が異なる場合):
using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{
}
また、コンマ区切り (型は同じ):
using (SqlCommand comm = new SqlCommand("", conn),
comm2 = new SqlCommand("", conn))
{
}
MemoryStream オブジェクトは適切に破棄されるため、心配する必要はありません。
このusing
ステートメントを使用すると、オブジェクトは完了パスに関係なく破棄されます。
参考文献...
コンパイルした後、リフレクターでコードを見てください。ストリームで dispose が確実に呼び出されるように、コンパイラがコードをリファクタリングすることがわかります。