7

真/偽の答えを期待していた別のインタビューの質問で、よくわかりませんでした.

複製

4

9 に答える 9

29

finallyほとんどの場合実行されます。ほとんどすべての場合です。たとえば、非同期例外(、、StackOverflowExceptionなどOutOfMemoryExceptionThreadAbortExceptionがスレッドでスローされた場合、finally実行は保証されません。これが、信頼性の高いコードを記述するために制約された実行領域が存在する理由です。

インタビューの目的で、私はこの質問への答えが間違っていることを期待しています(私は何も保証しません!インタビュアーはこれを自分で知らないかもしれません!)。

于 2009-05-07T10:57:01.230 に答える
8

通常、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);
}

私が知っているもう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ます。

例は非常に工夫されていることを認めますが、それらは要点を説明するために作成されたものです。

幸いなことに、どちらも頻繁には発生しません。

于 2009-05-07T11:03:15.973 に答える
8

MSDNから直接:

finally ブロックは、try ブロックで割り当てられたリソースをクリーンアップするのに役立ちます。try ブロックの終了方法に関係なく、制御は常に finally ブロックに渡されます。

catch は、ステートメント ブロックで発生する例外を処理するために使用されますが、finally は、前の try ブロックがどのように終了したかに関係なく、コードのステートメント ブロックが実行されることを保証するために使用されます。

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

于 2009-05-07T10:46:30.633 に答える
4

最終的に常に実行されるというのは完全に真実ではありません。Haackedからのこの回答を参照してください:

2つの可能性:

  • StackOverflowException
  • ExecutingEngineException

StackOverflowExceptionが発生した場合、スタックにはそれ以上コードを実行する余地がないため、finallyブロックは実行されません。また、非常にまれなExecutingEngineExceptionが発生した場合も呼び出されません。

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

Mehrdadが述べたように、信頼できるtry / catch / finalは、Constrained Execution Regions(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;
    }
}
于 2009-05-07T10:56:09.657 に答える
4

はい、finally は常に実行されます。

于 2009-05-07T10:44:59.997 に答える
1

一般に、finally ブロックは、例外がスローされるかどうか、および例外が処理されるかどうかに関係なく、常に実行されます。

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

于 2009-05-07T10:45:08.873 に答える
0

最後に、その try catch ブロックに対して毎回発生します

于 2009-05-07T10:45:50.883 に答える
0

「最後に」は、例外がスローされるかどうかに関係なく実行されます。

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

于 2009-05-07T10:49:03.573 に答える
-2

最後に常に実行されます。tryブロックがどのように機能するかに依存しません。tryとcathの両方で追加の作業を行う必要がある場合は、finallyブロックに入れることをお勧めします。したがって、常に実行されることを保証できます。

于 2009-05-07T11:11:11.167 に答える