次のコードを使用します。
using System;
namespace OddThrow
{
class Program
{
static void Main(string[] args)
{
try
{
throw new Exception("Exception!");
}
finally
{
System.Threading.Thread.Sleep(2500);
Console.Error.WriteLine("I'm dying!");
System.Threading.Thread.Sleep(2500);
}
}
}
}
これにより、次の出力が得られます。
Unhandled Exception: System.Exception: Exception!
at OddThrow.Program.Main(String[] args) in C:\Documents and Settings\username
\My Documents\Visual Studio 2008\Projects\OddThrow\OddThrow\Program.cs:line 14
I'm dying!
私の質問は:なぜ未処理の例外テキストが最終の前に発生するのですか? 私の考えでは、この例外が処理されていないことを知る前に、スタックが巻き戻されるときに finally を実行する必要があります。Sleep() の呼び出しに注意してください。これらは、ハンドルされていない例外が出力された後に発生します。
- 未処理の例外テキスト/メッセージ
- 最後にブロックします。
- アプリケーションを終了する
C# 標準の §8.9.5 によると、この動作は正しくありません。
- 現在の関数メンバーで、スロー ポイントを囲む各 try ステートメントが調べられます。各ステートメント S について、最も内側の try ステートメントから始まり、最も外側の try ステートメントで終わるまで、次のステップが評価されます。
- S の try ブロックがスロー ポイントを囲み、S に 1 つ以上の catch 句がある場合、catch 句は出現順に調べられ、例外に適したハンドラーが検索されます。例外の種類または例外の種類の基本型を指定する最初の catch 句は、一致と見なされます。一般的な catch 句 (§8.10) は、あらゆる例外タイプに一致すると見なされます。一致する catch 句が見つかった場合、その catch 句のブロックに制御を移すことによって、例外の伝播が完了します。
- それ以外の場合、S の try ブロックまたは catch ブロックがスロー ポイントを囲み、S に finally ブロックがある場合、制御は finally ブロックに転送されます。finally ブロックが別の例外をスローした場合、現在の例外の処理は終了します。それ以外の場合、制御が finally ブロックの終点に到達すると、現在の例外の処理が続行されます。
- 現在の関数メンバー呼び出しで例外ハンドラーが見つからなかった場合、関数メンバー呼び出しは終了します。上記の手順は、関数メンバーが呼び出されたステートメントに対応するスロー ポイントを使用して、関数メンバーの呼び出し元に対して繰り返されます。
- 例外処理が現在のスレッドのすべての関数メンバー呼び出しを終了し、スレッドに例外のハンドラーがないことを示す場合、スレッド自体が終了します。このような終了の影響は実装定義です。
どこが間違っていますか?(私はいくつかのカスタム コンソール エラー メッセージを持っていますが、これは邪魔です。些細なことで、面倒で、言語に疑問を抱かせます...)