0

重複の可能性:
finallyが.netで実行されない場合の条件try..finallyブロック
C#では、未処理の例外がスローされた場合、finallyブロックはtry、catch、finallyで実行されますか?

http://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java#Finally_Blocks_and_Uncaught_Exceptionsは、finallyブロックが常に実行されるとは限らないと述べています。それは間違っていますよね?

CLIのECMA標準(C#が例外機能を派生させる)では、例外はスタックの2パス検索で処理されると規定されています。[13] 最初のパスは、一致するcatchブロックを見つけようとし、何も見つからない場合はプログラムを終了します。一致するcatchブロックが見つかった場合にのみ、2番目のパスが実行され、間にあるfinallyブロックが実行されます。これにより、finallyブロックによってプログラムの状態が最初に変更されることなく、問題を診断できます。また、プログラムが不明な状態にあるときに、最終的にブロックが望ましくない副作用(外部データの破損やさらなる例外のスローなど)を引き起こす可能性があるリスクも排除します。

しかし、最終的に実行するためにキャッチは必要ありません。

    static void Main()
    {
        try { throw new Exception(); }
        finally
        {
            Console.WriteLine("1");
        }
    }
4

5 に答える 5

7

「このテキストは正しいですか?」というあなたの質問に実際に誰も答えていないことに気付きました。

いいえ、重要な点が省略されているという点で、正しくありません。

引用に失敗した CLI 仕様の関連部分は、Partition I のセクション 12.4.2 であり、次のように述べています。


finally ハンドラー ... は、ブロックが終了するたびに、それが通常の制御フローによって発生するか、未処理の例外によって発生するかに関係なく実行されます。


さて、他の人が指摘したように、ここにはいくつかの微妙な点があります. ブロックの終了時にfinally が実行されることを仕様が明確に示していることに注意してください。プログラムがフェイルファスト、スタック オーバーフロー、または誰かが電源コードを壁から引き抜くことによって終了した場合、ブロックは決して終了しませんブロックが終了する前にプログラムが終了する可能性があるため、finally は実行されません。

于 2010-01-12T17:36:31.270 に答える
1

このコードを試してください。最終的に呼び出されることはありません:

    static void Main()
    {
        try 
        {
            Environment.FailFast("failed");
        }
        finally
        {
            Console.WriteLine("finally!");
        }
    }
于 2010-01-12T12:43:07.883 に答える
0

これは、スタックのどこにも catch 句がない場合、つまり例外が処理されない場合、例外がスローされた時点ですぐに異常終了が発生することを意味します。

詳細な説明と回答については、C# の最終実行の時間を参照してください。

于 2010-01-12T11:31:42.687 に答える
0

finally ステートメントは通常実行されますが、TheDailyWTF.com のインタビューの話 ( http://thedailywtf.com/Articles/My-Tales.aspx )の 1 つ (私が思い出す限り) で指摘されているように、常に実行されるわけではありません。

私は(これについては間違っているかもしれませんが)、StackOverflowException は finally ブロックに分類されないと思います。(ThedailyWTF.com に投稿されたもう 1 つの素敵な例は、電源が切られた場合に finally ブロックが実行されないという単純なケースです;))。

したがって、常に実行されると信じないように注意してください。

于 2010-01-12T11:43:49.807 に答える
0

アセンブリのメイン メソッドがスタックの最初のメソッドではないことを忘れないでください。以下に、他のいくつかの方法 (マネージ メソッドとアンマネージ メソッドの組み合わせ) があります。これらのメソッドは、実行中のアセンブリを読み込み、最後にコマンド ライン引数を指定してメイン メソッドを呼び出します。

Visual Studio でマネージド アプリケーションをデバッグするときの一般的なコール スタックは次のようになります。

MyProgram.exe!MyProgram.Program.Main(string[] args = {string[0]}) Line 15   C#
[Native to Managed Transition]  
[Managed to Native Transition]  
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x3a bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes  
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   

このコール スタックのどこかに、ユーザー コードで処理されていない例外が発生した場合にスタック トレースを出力する catch ハンドラーがある場合があります。ただし、これは実装の詳細であり、仕様のセクション 12.4.2.5 と競合しません。

于 2010-01-12T12:11:40.313 に答える