try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
上記のブロックで、finallyブロックが呼び出されるのはいつですか?eを投げる前、または最後に呼び出されてから、キャッチする?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
上記のブロックで、finallyブロックが呼び出されるのはいつですか?eを投げる前、または最後に呼び出されてから、キャッチする?
回答:
eが再スローされた後(つまり、catchブロックが実行された後)に呼び出されます。
7年後のこの編集-重要な注意点の1つはe、try / catchブロックでキャッチされない場合、またはコールスタックの上位で処理されなかったり、グローバル例外ハンドラーで処理されなかった場合、finallyブロックがまったく実行されない可能性があることです。
finally、前にスローされた例外があれば実行されていないcatchん巻き込まない外にtry- catchブロック!
試してみませんか:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
コード付き(垂直スペース用にフォーマット済み):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
outer try inner try inner catch Unhandled Exception: System.DivideByZeroException...
ここですべての回答を読んだ後、最終的な回答は次のようになります:
catchブロック内で例外を再スローし、その例外が別のcatchブロック内でキャッチされた場合、ドキュメントに従ってすべてが実行されます。
ただし、再発生した例外が処理されない場合、finallyは実行されません。
このコードサンプルをVS2010 w / C#4.0でテストしました
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
出力は次のとおりです。
例1:別のtryブロックの内部で再スローする:--
outer try
---- inner try
---- inner catch
---- inner finally
--outer catch
--outer finally
Huzzah!例2:別のtryブロックの外で再スローする:--
try
--catch未処理の例外:System.Exception:タイプ 'System.Exception'の例外がスローされました。
C:\ local source \ ConsoleApplication1 \ Program.cs:line 53のConsoleApplication1.Program.Main()で
あなたの例はこのコードと同じように動作します:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
補足として、本当に意味する場合throw e;(つまり、キャッチしたのと同じ例外をスローする場合)は、新しいスタックトレースを作成する代わりに、元のスタックトレースを保持するため、を実行する方がはるかに優れていthrow;ます。
finallyブロックは、実際には後に実行されますcatch私のスニペットを説明しようとしているものであるブロック(catchブロックが例外を再スローした場合でも)、。
tryブロックの内側に「トライ・キャッチ」があります。2つの2部構成を使用して、3部構成の動作を説明しようとしています。try元の質問には2番目のブロックの兆候が見当たらないので、どこでそれが得られているのかわかりません。
キャッチハンドラブロック内に未処理の例外がある場合、finallyブロックは正確に0回呼び出されます
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
出力:
C:\ users \ administrator \ documents \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe
試してみて
キャッチで
未処理の例外:System.DivideByZeroException:ゼロで除算しようとしました。TestExceptionNesting.Program.Main(String [] args)at C:\ users \ administrator \ documents \ TestExceptionNesting \ TestExceptionNesting.cs:line 22
C:\ users \ administrator \ documents \ TestExceptionNesting \ bin \ release>
今日、この質問はインタビューで聞かれましたが、インタビュアーは「最後に呼び出されないのは確かですか?」トリックの質問なのか、インタビュアーが何か他のことを考えていて、デバッグするために間違ったコードを書いたのかどうかわからなかったので、帰宅してそれを試してみました(ビルドと実行、デバッガーの相互作用なし)。残り。
C#コンソールアプリケーションでのテストでは、例外がスローされた後、最終的にコードが実行されました。「アプリケーションエラーダイアログ」が存在し、「プログラムを閉じる」オプションを選択した後、そのコンソールウィンドウでfinallyブロックが実行されました。しかし、finallyコードブロック内にブレークポイントを設定すると、私はそれにぶつかることはありません。デバッガーは、throwステートメントで停止し続けます。これが私のテストコードです:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
VS2010でのデバッグ-.NET Framework 4.0