2010-11-29 10 views

答えて

95

はい、絶対になります。 finallyブロックが例外をスローしないと仮定すると、当然、最初にスローされたブロックを効果的に「置き換える」ことになります。

+0

またはそれが –

+8

を返すかどうか@David:C#のfinallyブロックから戻ることはできません。 –

+1

[msdnドキュメント](http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx)もこの回答を確認しています。_代わりに、try-tryブロックのtryブロックにスローされた可能性のある例外を検出できます。最後に、呼び出しスタックを上げます。つまり、try-finallyステートメントを含むメソッドを呼び出すメソッド、またはそのメソッドを呼び出すメソッド、または呼び出しスタック内のすべてのメソッドで例外をキャッチすることができます。例外がキャッチされない場合、finallyブロックの実行は、オペレーティングシステムが例外の巻き戻し操作をトリガするかどうかによって異なります。_ – broadband

52

一般的な考え方はありますか?

はい。 注意してください。 finallyブロックが実行されているとき、処理されていない、予期しない例外がにスローされたため、が実行されている可能性があります。つまり、何かがが壊れた、そして何かが全く予期しない何かが起きている可能性があります。

おそらく、最終的なブロックでコードを実行しないでください。 finallyブロックのコードは、依存するサブシステムが健全であると仮定するように構築されていても、実際には深く壊れている可能性があります。 finallyブロックのコードは状況を悪化させる可能性があります。例えば

、私は多くの場合、この種のものを参照してください。このコードの作者は、私は世界の状態を一時的に変異を作っています」考えている

DisableAccessToTheResource(); 
try 
{ 
    DoSomethingToTheResource(); 
} 
finally 
{ 
    EnableAccessToTheResource(); 
} 

を、私はに状態を復元する必要があります私が呼び出される前は何だったのか」しかし、これが間違っている可能性があるすべての方法について考えてみましょう。

最初に、リソースへのアクセスは、呼び出し元によってすでに無効にされている可能性があります。その場合、このコードはおそらく時期尚早にそれを再び有効にします。

第2に、DoSomethingToTheResourceが例外をスローした場合、リソースへのアクセスを可能にするために正しいことがありますか?リソースを管理するコードは、が予期せず壊れていますです。このコードでは、「管理コードが壊れている場合、は、他のコードが破損したコードをできるだけ早く呼び出すことができるので、恐ろしく失敗する可能性があることを確認しています。」これは悪い考えのようです。

第3に、DoSomethingToTheResourceが例外をスローすると、EnableAccessToTheResourceも例外をスローしないことをどのように知ることができますか?リソースの使用がクリーンアップコードに影響を与える可能性がありますが、元の例外は失われ、問題は診断するのが難しくなります。

私は、try-finallyブロックを使用せずに、このようなコードを記述する傾向がある:

bool wasDisabled = IsAccessDisabled(); 
if (!wasDisabled) 
    DisableAccessToTheResource(); 
DoSomethingToTheResource(); 
if (!wasDisabled) 
    EnableAccessToTheResource(); 

それはする必要がありますしない限り、今の状態が変異していません。今、発信者の状態は乱されていません。 DoSomethingToTheResourceが失敗した場合は、再度アクセスを有効にしません。何かが深刻に壊れていると想定し、コードを実行し続けることによって状況を悪化させる危険性はありません。可能であれば、発信者に問題に対処させてください。

だから、finallyブロックを実行するのは良い考えですか?最初に、例外が予想されるとき。たとえば、他の誰かがロックしているため、ファイルをロックしようとする試みが失敗する可能性があります。その場合、例外をキャッチしてユーザーに報告するのが理にかなっています。その場合、何が壊れているのかに関する不確実性は減少する。あなたは浄化することによって物事を悪化させることはまずありません。

第2に、クリーンアップするリソースが不足しているシステムリソースである場合。たとえば、finallyブロック内のファイルハンドルを閉じることは理にかなっています。 (「使用する」とは、もちろんtry-finallyブロックを書き込む別の方法です)。ファイルの内容が壊れている可能性がありますが、今はそれについて何もできません。ファイルハンドルは最終的に閉じられるので、遅くなくても早くなる可能性があります。

+4

さらに、実際にはエラー処理。例外よりも提案するほうがいいとはいえませんが、未来が合理的に簡単に取られる行動の正しい過程につながる可能性がより高くなることを期待しています。 –

+0

vb.netでは、finallyブロック内のコードが保留中の例外を知ることができます。保留中の例外が不良のものでない場合、 "それはしなかった、それ以外の場合は大丈夫"と "状態が壊れている"とを区別するために例外階層を設定すると、finallyブロックのみが実行されます。 Disposer/Cleanupルーチンが例外をキャッチしてDisposerFailedException( "bad"カテゴリにあり、元の例外をInnerExceptionとして含む)をスローするのが好きです。私は、標準のiDisposableExインターフェイスをDispose(Ex as Exception)を使って見てみたいと思っています。 – supercat

+0

オブジェクトが悪い状態にある間に例外が発生し、クリーンアップを試みると状態が悪化する場合がありますが、このような問題はクリーンアップコードで処理しなければならないと思います。たとえば、ロックラッパーは、ロックされたオブジェクトが無効な状態にあるときに設定され、そうでなければクリアされる「CheckIfSafeToUnlock(Ex as Exception)」関数デリゲートを公開する可能性があります。ロックを解除する前に、ラッパーはデリゲートをチェックできます。空でない場合、それを実行し、trueを返す場合にのみロックを解放することができます。 – supercat

関連する問題