次のコードC#コードを検討してください。 「最終」ブロックは実行されますか?
public void DoesThisExecute() {
string ext = "xlsx";
string message = string.Empty;
try {
switch (ext) {
case "xls": message = "Great choice!"; break;
case "csv": message = "Better choice!"; break;
case "exe": message = "Do not try to break me!"; break;
default:
message = "You will not win!";
return;
}
}
catch (Exception) {
// Handle an exception.
}
finally {
MessageBox.Show(message);
}
}
ハ、これを書いた後、私はVisual Studioでこれを自分でテストできたことに気付きました。ただし、お気軽にご回答ください!
try
ステートメントのMSDN C#仕様から:
finally
ブロックのステートメントは、制御がtry
ステートメントを離れると常に実行されます。これは、break
、continue
、goto
、またはreturn
ステートメントを実行した結果として、通常の実行の結果としてコントロール転送が発生する場合でも当てはまります。 、またはtry
ステートメントから例外を伝播した結果として。
Finallyブロックが実行されない場合があります。
finally
が常に実行されるとは限りません。 この回答 from Haacked を参照してください:
2つの可能性:
StackOverflowException
ExecutingEngineException
StackOverflowExceptionが発生すると、finallyブロックは実行されません。スタックにコードを実行する余地がないためです。また、非常にまれなExecutingEngineExceptionがある場合にも呼び出されません。
実際、あらゆる種類の非同期例外(StackOverflowException
、OutOfMemoryException
、ThreadAbortException
など)の場合、finally
ブロックの実行は保証されません。
ただし、これらの例外は通常は回復できない例外であり、ほとんどの場合、プロセスは終了します。
実際、 Brian Rasmussen by now deleted question で説明されているように、finally
が実行されない他のケースも少なくとも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();
}
}
信頼できるtry/catch/finallyは 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;
}
}
優れた情報源は次の記事です。
MSDNから try-finally(C#リファレンス)
Finallyブロックは、tryブロックに割り当てられたリソースをクリーンアップしたり、例外が発生した場合でも実行する必要があるコードを実行したりするのに役立ちます。 tryブロックがどのように終了するかに関係なく、制御は常にfinallyブロックに渡されます。
はい、通常の状況では(他の多くの人が指摘しているように)。
Finallyブロックは、tryブロックに割り当てられたリソースをクリーンアップしたり、例外が発生した場合でも実行する必要があるコードを実行したりするのに役立ちます。 tryブロックの終了方法に関係なく、制御は常にfinallyブロックに渡されます。
Catchはステートメントブロックで発生する例外の処理に使用されますが、finallyは前のtryブロックの終了方法に関係なくコードのステートメントブロックの実行を保証するために使用されます。
これらの行の間で、finallyブロックが実行されます。
message = "You will not win!";
return;
はい、finally
は常に実行されますが、finallyブロックのコードが例外を引き起こすかどうかは別の話です。
正解は「はい」です。
プログラムをデバッグし、ブレークポイントを設定して、コントロールが最終ブロックにヒットするのを確認してください。
いいえ、そうではありません。
しかし、それを回避する方法は1つしかなく、それはEnvironment.FailFast()
です。 http://msdn.Microsoft.com/de-de/library/ms131100.aspx を参照してください。他のすべてのケースでは、ファイナライザが実行されることが保証されています;-)
FailFastメソッドは、メッセージ文字列をWindowsアプリケーションイベントログに書き込み、アプリケーションのダンプを作成してから、現在のプロセスを終了します。メッセージ文字列は、Microsoftへのエラー報告にも含まれています。
アプリケーションの状態が修復できないほど破損している場合、Exitメソッドの代わりにFailFastメソッドを使用してアプリケーションを終了します。アプリケーションのtry/finallyブロックとファイナライザを実行すると、プログラムリソースが破損します。
簡単な答えはい。しかし、ルールにはいくつかの「例外」があります。