4
try
{
    try
    {
        throw new Exception("From Try");
    }
    catch
    {
        throw new Exception("From Catch");
    }
    finally
    {
        throw new Exception("From Finally");
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

上記のコードの出力は次のとおりですFrom Finally

なぜそうではないのFrom Catchですか?

-また-

両方の例外をキャッチしてログに記録するにはどうすればよいですか?

4

8 に答える 8

6

finallyブロックはcatchブロックの後に実行されるため、例外をオーバーライドします。

また、以前の例外の処理中に例外が発生すると、最初の例外は失われます。

両方の例外の外部からキャッチしてログに記録するにはどうすればよいですか?

  1. ファイナルブロックの中に投げ込まないことによって。それは常に悪い考えです。
  2. 内部catchブロックにログインする場合はthrow;、最初の例外を使用するか、新しい例外のInnerExceptionとして渡します。InnerException それが存在する理由です。
于 2010-09-29T22:35:15.917 に答える
3

これは、C# 言語仕様で定義されている動作です。ブロック内でスローされた例外の処理tryは中止され、代わりにブロック内でスローされた例外finallyが処理されます。

関連するセクション8.9.5 throw ステートメントでは、例外がどのように伝播されるかを説明しています。

  • 現在の関数メンバーでtry、スロー ポイントを囲む各ステートメントが調べられます。S最も内側のtryステートメントから最も外側のステートメントまで、ステートメントごとtryに次のステップが評価されます。

    • の try ブロックがSスロー ポイントを囲み、S1 つ以上catchの句がある場合、catch句は出現順に調べられ、例外に適したハンドラが検索されます。catch例外タイプまたは例外タイプの基本タイプを指定する最初の句は、一致と見なされます。一般catch節 ( §8.10) は、すべての例外タイプに一致すると見なされます。一致するcatch句が見つかった場合、その句のブロックに制御を移すことによって、例外の伝播が完了しcatchます。

    • それ以外の場合、tryブロックまたは のcatchブロックがSスロー ポイントを囲み、Sfinally ブロックがある場合、制御は finally ブロックに転送されます。ブロックが別の例外をスローした場合、finally現在の例外の処理は終了します。それ以外の場合、制御がブロックの終点に到達するfinallyと、現在の例外の処理が続行されます。

于 2010-09-29T22:49:53.053 に答える
1

次のように、try-catch ブロックのレイヤーを追加します。

try {
    Exception fromCatch = null;
    try {
        throw new Exception("From Try");
    }
    catch {
        try {
            throw new Exception("From Catch");
        }
        catch (Exception e) {
            // catch failed -> store exception
            fromCatch = e;
        }
    }
    finally {
        try {
            throw new Exception("From Finally");
        }
        catch (Exception e) {
            // i can think of better exception merging... but this shows the idea
            throw new Exception(e.Message, fromCatch);
        }
        // throw fromCatch, in case "From Finally did not happen"
        throw fromCatch;
    }
}
catch (Exception ex) {
    Console.WriteLine(ex.Message);
    if (ex.InnerException != null) {
        Console.WriteLine(ex.InnerException.Message);
    }
}

レポート:

From Finally
From Catch

編集:「なぜ」が十分に答えられているので、これは明らかに質問2の答えです:)

于 2010-09-29T23:41:08.223 に答える
0

最後に常に実行されます。そしてそれは常に最後に実行されます。それで、内側の試みによって行われた最後のことは最終的にであり、それは外側のキャッチによって捕らえられた何かを投げました

質問のパート2を理解しているかどうかわからない

于 2010-09-29T22:33:50.723 に答える
0

finally何があっても起こります。tryまたはcatchに例外があったかどうかに関係なく。したがって、「FromFinally」が表示されます。(これは実際には句の全体的な目的ですfinally。したがって、例外があったとしても、リソースなどをクリーンアップするコードをそこに入れることができます。)

于 2010-09-29T22:34:25.900 に答える
0

これは非常に良い質問であり、ちょっと注意が必要です。このステップバイステップを見ていきましょう:

try
{
    throw new Exception("From Try");
}
catch
{
    throw new Exception("From Catch");
}

上記のコードでは、Exception( "From Try")がスローされ、catch句によってキャッチされます(これまでのところ非常に単純です)。catch句は、それ自体の例外をスローします。これは通常、(catchがより大きなtry-catchブロックにネストされているため)すぐにキャッチされると予想されますが、...

finally
{
   throw new Exception("From Finally");
}

実行する(実行しようとする)ことが保証されているfinally句が最初に来て、それ自体の例外をスローし、前にスローされたException( "From Catch")を上書きします。

「catchおよびfinallyを一緒に使用する一般的な使用法は、tryブロックでリソースを取得して使用し、catchブロックで例外的な状況に対処し、finallyブロックでリソースを解放することです」-MSDN記事

この一連のロジックに従って、キャッチにコードを記述しないように最善を尽くし、最後に例外が発生しやすいブロックを作成する必要があります。提示したような状況が発生することが心配な場合は、例外とその関連情報を外部ファイルにログアウトして、デバッグ用に参照できるようにすることをお勧めします。

于 2010-09-29T23:02:48.407 に答える
0

コードは、try/catch/finally ステートメントの各部分から新しい例外をスローします。新しいエラーを作成すると、本質的に以前の例外を飲み込んでいます。「From Try」メッセージを「From Catch」メッセージに次のように追加できます

catch(Exception ex)
{
    throw new Exception(ex.Message + ":" + "From Catch");
}

最終的にそれを連鎖させる方法がわかりません。

于 2010-09-29T22:45:16.070 に答える
0

finally ブロックは常に実行されるためです。

try 
{ 
    try 
    { 
        throw new Exception("From Try"); 
        // (1) A new exception object A is created here and thrown.
    } 
    catch // (2) Exception object A is catched.
    { 
        throw new Exception("From Catch"); 
        // (3) A new exception object B is created here and thrown.
    } 
    finally // (4) Execution is forced to continue here!
    { 
        throw new Exception("From Finally"); 
        // (5) A new exception object C is created here and thrown.
    } 
} 
catch (Exception ex) // (6) Exception object C is catched.
{ 
    Console.WriteLine(ex.Message); 
} 

ステップ (3) および (5) で新しく作成されたすべての例外オブジェクトは、前のものを破棄します。finally ブロックは常に実行されるため、残っているのはステップ (5) の例外オブジェクト C だけです。

于 2010-09-29T22:46:56.160 に答える