5

もう一つのインタビューの質問は、真偽の答えを期待していましたが、私はあまりわかりませんでした。

複製する


10 답변


26

finally実行されますほとんどの時間。ほとんどすべての場合です。たとえば、非同期例外(次のような場合)StackOverflowExceptionOutOfMemoryExceptionThreadAbortException)スレッドにスローされます。finally実行は保証されていません。これが理由です制約付き実行領域信頼性の高いコードを書くために存在します。

面接のために、この質問に対する答えは(私は何も保証しません!インタビュアーはこれを自分で知らないかもしれません!)


  • 非常に興味深い、これまでCERについて聞いたことがない。ここでそれを上げてくれてありがとう。 - Colin Desmond
  • +1これは見逃されがちで非常に重要な点です! 「ようやく」と言うのは危険です。常にあなたが指摘した理由で実行されます。いい答えだ。 - Andrew Hare
  • 完全に同意しました。私は問題の原因はMSDN自身だと思います。それは、受け入れられた答えの中で言及されたもののようなリンクにおいてこの事実の意識を高めるはずです。 MSDN自体が「直前のtryブロックの終了方法に関係なく、コードブロックが実行されることを保証するために最後に使用されます」これは間違っています、これは結果になります。知っている非常に少ないこの質問に「はい」と答えない人。 - Mehrdad Afshari
  • 誰かが宿題をしているのを見ます、素晴らしい答えです!とても面白い記事です。 - John T
  • また、電源が切れた、ハードウェアが誤動作した、OSがプロセスを終了したなどの理由で実行されないという、より一般的なケースを忘れないでください。ファイルとOSがあなたを殺し、最後のブロックがあなたを救うことはできませんでした。 - Craig Gidney

7

一般的にfinallyブロックは実行が保証されています。

ただし、いくつかのケースでは、エラーが発生した場合にCLRを強制的にシャットダウンします。そのような場合、finallyブロックは実行されません。

そのような例の1つは、StackOverflow例外の存在です。

例えば。下のコードでfinallyブロックは実行されません。

static void Main(string[] args) {
   try {
      Foo(1);
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public static int Foo(int i) {
   return Foo(i + 1);
}

私が知っている他のケースは、ファイナライザが例外を投げた場合です。その場合、プロセスもすぐに終了し、保証は適用されません。

以下のコードは問題を示しています

static void Main(string[] args) {
   try {
      DisposableType d = new DisposableType();
      d.Dispose();
      d = null;
      GC.Collect();
      GC.WaitForPendingFinalizers();
   } catch {
      Console.WriteLine("catch");
   } finally {
      Console.WriteLine("finally");
   }
}

public class DisposableType : IDisposable {
   public void Dispose() {
   }

   ~DisposableType() {
      throw new NotImplementedException();
   }
}

どちらの場合も、プロセスは両方の前に終了します。catchそしてfinally

私は例が非常に人為的であることを認めます、しかしそれらは単に要点を説明するために作られています。

幸い、どちらも頻繁には起こりません。


  • 興味深い点ですが、2番目の例は別の/保護されていないスレッドで発生したため、例外をキャッチしません。 - Matthew Whited
  • 例としてStackOverflowを使用する場合は+1 :-) - Josh

6

MSDNから直接:

finallyブロックは   に割り当てられたリソースをクリーンアップする   tryブロックコントロールは常に   に関係なくfinallyブロックに渡されます   tryブロックの終了方法

捕獲物が処理に使用されるのに対して   ステートメントで発生する例外   ブロック、最後にを保証するために使用されます   コードブロックのステートメントブロック   前の試みがどうであろうと関係なく   ブロックは終了します。

http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx



3

はい、ついにいつも実行されます。


3

最終的に常に実行されることは完全には真実ではありません。見るこの答えからハッキング

2つの可能性

  • StackOverflowException
  • ExecutingEngineException

finallyブロックは実行されません   StackOverflowExceptionがある場合   スタックには余裕がないので   これ以上コードを実行しないでください。そうなる   またあるときに呼ばれない   ExecutingEngineException、これは   非常にまれな。

ただし、これら2つの例外は回復できない例外なので、基本的にはとにかくプロセスは終了します。

Mehrdadが述べたように、信頼できるtry / catch /がついに使用しなければならなくなるでしょう。制約付き実行領域(CER)。あMSDNによって提供されます。

[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
    public IntPtr m_outputHandle;
}

sealed class MySafeHandle : SafeHandle
{
    // Called by P/Invoke when returning SafeHandles
    public MySafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public MySafeHandle AllocateHandle()
    {
        // Allocate SafeHandle first to avoid failure later.
        MySafeHandle sh = new MySafeHandle();

        RuntimeHelpers.PrepareConstrainedRegions();
        try { }
        finally
        {
            MyStruct myStruct = new MyStruct();
            NativeAllocateHandle(ref myStruct);
            sh.SetHandle(myStruct.m_outputHandle);
        }

        return sh;
    }
}


1

通常、finallyブロックは、例外がスローされるかどうか、および例外が処理されるかどうかにかかわらず、常に実行されます。

例外がいくつかあります(詳細については他の回答を参照してください)。


0

例外がスローされたかどうかにかかわらず、 'finally'が実行されます。

開いている接続を閉じるのに適した場所です。実行が成功または失敗した場合でも、接続を管理したりファイルを開くことができます。


-1

最後にそのtry catchブロックのたびに発生します


-1

最後にblockはいかなる場合でも実行されることが保証されています。


-1

最後に常に実行されます。 tryブロックがどのように機能するかには依存しません。 もしtryとcathの両方に余分な作業をしなければならない場合は、finallyブロックを入れた方が良いでしょう。だからあなたはそれが常に実行されることを保証することができます。

リンクされた質問


関連する質問

最近の質問