もう一つのインタビューの質問は、真偽の答えを期待していましたが、私はあまりわかりませんでした。
finally
実行されますほとんどの時間。ほとんどすべての場合です。たとえば、非同期例外(次のような場合)StackOverflowException
、OutOfMemoryException
、ThreadAbortException
)スレッドにスローされます。finally
実行は保証されていません。これが理由です制約付き実行領域信頼性の高いコードを書くために存在します。
面接のために、この質問に対する答えは偽(私は何も保証しません!インタビュアーはこれを自分で知らないかもしれません!)
一般的に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
。
私は例が非常に人為的であることを認めます、しかしそれらは単に要点を説明するために作られています。
幸い、どちらも頻繁には起こりません。
MSDNから直接:
finallyブロックは に割り当てられたリソースをクリーンアップする tryブロックコントロールは常に に関係なくfinallyブロックに渡されます tryブロックの終了方法
捕獲物が処理に使用されるのに対して ステートメントで発生する例外 ブロック、最後にを保証するために使用されます コードブロックのステートメントブロック 前の試みがどうであろうと関係なく ブロックは終了します。
http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx
はい、ついにいつも実行されます。
最終的に常に実行されることは完全には真実ではありません。見るこの答えからハッキング:
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;
}
}
通常、finallyブロックは、例外がスローされるかどうか、および例外が処理されるかどうかにかかわらず、常に実行されます。
例外がいくつかあります(詳細については他の回答を参照してください)。
例外がスローされたかどうかにかかわらず、 'finally'が実行されます。
開いている接続を閉じるのに適した場所です。実行が成功または失敗した場合でも、接続を管理したりファイルを開くことができます。
最後にそのtry catchブロックのたびに発生します
最後にblockはいかなる場合でも実行されることが保証されています。
最後に常に実行されます。 tryブロックがどのように機能するかには依存しません。 もしtryとcathの両方に余分な作業をしなければならない場合は、finallyブロックを入れた方が良いでしょう。だからあなたはそれが常に実行されることを保証することができます。