一般的にはい、最終的に実行されます。
次の3つのシナリオでは、finallyは常に実行されます。
- 例外は発生しません
- 同期例外(通常のプログラムフローで発生する例外)。
これには、System.Exceptionから派生するCLS準拠の例外と、System.Exceptionから派生しないCLS準拠以外の例外が含まれます。CLSに準拠していない例外は、RuntimeWrappedExceptionによって自動的にラップされます。C#ではCLS以外のクレーム例外をスローできませんが、C ++などの言語ではスローできます。C#は、CLSに準拠しない例外をスローできる言語で記述されたコードを呼び出す可能性があります。
- 非同期ThreadAbortException
.NET 2.0以降、ThreadAbortExceptionは、finallyの実行を妨げなくなりました。ThreadAbortExceptionは、finallyの前または後にホイストされるようになりました。finallyは常に実行され、スレッドの中止が発生する前に試行が実際に入力されている限り、スレッドの中止によって中断されることはありません。
次のシナリオでは、finallyは実行されません。
非同期StackOverflowException。
.NET 2.0以降、スタックオーバーフローによりプロセスが終了します。さらに制約を適用して最終的にCER(制約付き実行領域)にしない限り、finallyは実行されません。CERは、一般的なユーザーコードでは使用しないでください。これらは、クリーンアップコードを常に実行することが重要な場合にのみ使用してください。すべてのプロセスがスタックオーバーフローでシャットダウンされ、すべての管理対象オブジェクトがデフォルトでクリーンアップされます。したがって、CERが関連する唯一の場所は、管理されていないハンドルなど、プロセスの外部に割り当てられたリソースの場合です。
通常、アンマネージコードは、ユーザーコードによって使用される前に、マネージクラスによってラップされます。マネージラッパークラスは、通常、SafeHandleを使用してアンマネージハンドルをラップします。SafeHandleは、重要なファイナライザと、クリーンアップコードの実行を保証するためにCERで実行されるReleaseメソッドを実装します。このため、CERがユーザーコード全体に散らばって表示されることはありません。
したがって、プロセスがとにかく終了するため、finallyがStackOverflowExceptionで実行されないという事実は、ユーザーコードに影響を与えません。SafeHandleまたはCriticalFinalizerObjectの外でアンマネージリソースをクリーンアップする必要がある特別なケースがある場合は、次のようにCERを使用します。ただし、これは悪い習慣です。アンマネージドコンセプトは、マネージドクラスと適切なSafeHandleに設計によって抽象化する必要があります。
例えば、
// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// This is *NOT* a CER
}
finally
{
// This is a CER; guaranteed to run, if the try was entered,
// even if a StackOverflowException occurs.
}