いくつかの初期テストのように見えますが、私が知りたいのは、それが保証戻るのか、場合によっては戻れないのかということです。これは私のアプリケーションにとって重要ですが、それが戻らないユースケースはまだ見つかりません。
このテーマに関する専門知識を取得したいのですが。
Finishブロック内のすべては、tryブロックまたはcatchブロック内で何が起こったかに関係なく、常に実行されます。メソッドから戻るかどうかは関係ありません。
これに対する唯一の例外は、finallyブロックのコードが例外をスローした場合、他のコードブロックと同様に実行を停止することです。
Gotoに関しては、答えはまだイエスです。次のコードについて考えてみます。
try
{
Console.WriteLine("Inside the Try");
goto MyLabel;
}
finally
{
Console.WriteLine("Inside the Finally");
}
MyLabel:
Console.WriteLine("After the Label");
生成される出力は次のとおりです。
トライの内部
最後に中
ラベルの後
他の回答には多くの不正確さがあります。
制御がtryブロックを離れると、制御はfinallyブロックに渡されます通常-つまり、return、goto、break、continue、または単に終了から外れます。コントロールがtryブロックを離れると、finallyブロックにコントロールが渡されます囲んでいるcatchブロックによってキャッチされた例外を介して。
他のすべての状況では、finallyブロックのコードが呼び出されるというguaranteeはありません。特に:
Tryブロックコードが無限ループに入った場合、またはスレッドがフリーズしてフリーズ解除されなかった場合、finallyブロックコードは呼び出されません。
プロセスがデバッガーで一時停止されてから積極的に強制終了された場合、finallyブロックは呼び出されません。プロセスがフェイルファストを実行する場合、finallyブロックは呼び出されません。
電源コードが壁から引き出された場合、finallyブロックは呼び出されません。
例外がスローされた場合対応するcatchブロックなしの場合、finallyブロックが実行されるかどうかはランタイムの実装の詳細です。キャッチされない例外がある場合、ランタイムは任意の動作を選択できます。 「finallyブロックを実行しない」と「finallyブロックを実行する」はどちらも「任意の動作」の例であるため、どちらかを選択できます。通常、ランタイムが行うことは、finallyブロックが実行される前にデバッガーを接続するかどうかをユーザーに尋ねることです。ユーザーが「いいえ」と言った場合、finallyブロックが実行されます。しかし、繰り返しになりますが、ランタイムはそれを行うために必須ではありません。すぐに失敗する可能性があります。
常に呼び出されるfinallyブロックに依存することはできません。コードの実行について強力な保証が必要な場合は、try-finallyを作成するのではなく、 制約付き実行領域 を作成する必要があります。 CERを正しく記述することは、C#プログラミングで最も難しいタスクの1つであるため、コードを記述する前に、ドキュメントを注意深く調べてください。
ちなみに、最終的にブロックされたgotoに関する「面白い事実」は次のとおりです。
try { goto X; } finally { throw y; }
X : Console.WriteLine("X");
Xは、到達可能なgotoがターゲットとする到達不能なラベルです。したがって、次にパーティーに参加するときは、「みなさん、到達可能なgotoのターゲットとなる到達不能なラベルを持つC#プログラムを誰かが作成できますか?」のようになります。パーティーの誰が到達可能性の仕様を読んだのか、誰が読んでいないのかがわかります。
ここではいくつかの例を示します。
Environment.FailFast()
try
{
Console.WriteLine("Try");
Environment.FailFast("Test Fail");
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
出力は「試してみる」だけです
Stackoverflow
try
{
Console.WriteLine("Try");
Rec();
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
Console.WriteLine("finally");
}
Recはどこにありますか:
private static void Rec()
{
Rec();
}
出力は「試行」のみで、StackOverflowが原因でプロセスが終了します。
手渡しの例外
try
{
Console.WriteLine("Try");
throw new Exception();
}
finally
{
Console.WriteLine("finally");
}
アプリケーションを終了する致命的な例外の場合Finallyブロックは呼び出されません。スタックオーバーフロー、呼び出すメソッドのJIT中の例外、致命的な例外がCLRランタイムを要求します。
@mintechが指摘しているように、アプリケーションがブロック内でハングした場合、最終的にブロックに到達することはありません。これには、同期オブジェクトの待機、無限ループのデッドロック、またはそれを閉じる方法がないUIも含まれます。