C#“使用”構文
-
02-07-2019 - |
質問
usingは例外をキャッチまたはスローしますか?つまり
using (StreamReader rdr = File.OpenText("file.txt"))
{
//do stuff
}
streamreaderが例外をスローする場合、呼び出し関数がそれを処理できるように使用またはスローされることでキャッチされますか?
解決
ステートメントの使用は例外を食べません。
すべて"使用中"オブジェクトをusingブロックにスコープし、ブロックを離れるときにオブジェクトでDispose()を自動的に呼び出します。
ただし、スレッドが外部ソースによって強制的に中止された場合、Disposeが呼び出されない可能性があります。
他のヒント
usingステートメントが表示されたら、次のコードを考えてください:
StreadReader rdr = null;
try
{
rdr = File.OpenText("file.txt");
//do stuff
}
finally
{
if (rdr != null)
rdr.Dispose();
}
つまり、本当の答えは、usingブロックの本体でスローされた例外に対しては何もしないということです。処理も再スローもしません。
using
例外が沸騰するのを許可します。最終的に使用済みオブジェクトを破棄するtry / finallyのように動作します。したがって、 IDisposable
を実装するオブジェクトにのみ適切/有用です。
例外をスローするため、包含メソッドで処理するか、スタックに渡す必要があります。
try
{
using (
StreamReader rdr = File.OpenText("file.txt"))
{ //do stuff
}
}
catch (FileNotFoundException Ex)
{
// The file didn't exist
}
catch (AccessViolationException Ex)
{
// You don't have the permission to open this
}
catch (Exception Ex)
{
// Something happened!
}
usingステートメントの初期化式でスローされるすべての例外は、メソッドスコープを上に伝播し、期待どおりにスタックを呼び出します。
ただし、注意すべき点の1つは、初期化式で例外が発生した場合、式変数でDispose()メソッドが呼び出されないことです。実際に作成されていないオブジェクトを破棄するのは面倒なので、これはほとんど常に必要な動作です。ただし、複雑な状況では問題が発生する可能性があります。つまり、コンストラクター内に複数の初期化が埋め込まれ、例外がスローされる前にいくつかの初期化が成功した場合、その時点でDispose呼び出しが発生しない場合があります。ただし、コンストラクタは通常シンプルに保たれるため、これは通常は問題ではありません。
この例では、 File.OpenText
がスローされた場合、 Dispose
は 呼び出されません。
例外が // do stuff
で発生した場合、 Dispose
が呼び出されます。
どちらの場合も、例外は using ステートメントがない場合と同様に、通常スコープの外に伝播されます。
例外を特にキャッチしない場合、何かがキャッチされるまでスタックをスローします
使用は、スコープ内の内容をクリーンアップすることを除いて、例外処理を妨げません。
例外は処理しませんが、例外は通過させます。
using
は、例外がスローされた場合でも、作成されたオブジェクトがブロックの最後に破棄されることを保証します*。例外はキャッチされません 。ただし、自分でキャッチしようとする場合は、何をするかについて注意する必要があります。例外をキャッチするコードは using
ステートメントで定義されたスコープブロックの外側にあるため、オブジェクトはそのコードで使用できません。
*停電、核ホロコーストなどの通常の容疑者を除外
catchブロックなしで try ... finally ブロックとして使用を想像できます。 finallyブロックでIDisposable.Disposeが呼び出され、catchブロックがないため、例外がスタックにスローされます。
"使用&quot ;;例外をキャッチせず、未処理の例外が発生した場合にリソースを破棄するだけです。
おそらく問題は、宣言でエラーが発生した場合、括弧内に割り当てられたリソースを破棄することでしょうか?ただし、両方が発生することを想像するのは困難です。