Destructor Throw¶
What does this mean ?¶
C# syntax such as ~Example() declares a finalizer. It is not a C++ destructor executed deterministically when a local variable leaves scope. The garbage collector controls finalization timing, and an unhandled finalizer exception can terminate the process.
What can happen ?¶
Cleanup can disrupt application availability or occur too late for resource needs. Finalizers must not depend on other managed objects being finalized in a particular order. This reliability concern requires context before assigning security impact.
Recommendation¶
Do not throw from a finalizer. Prefer SafeHandle for unmanaged handles and IDisposable/using for deterministic cleanup. Do not add an empty finalizer to a class that has no finalization requirement. Catching every exception without a cleanup design is not an adequate replacement.
Sample Code¶
// Incorrect: never run this example to test the process-termination behavior.
class BrokenFinalizer
{
~BrokenFinalizer() { throw new NotImplementedException(); }
}
A class owning no unmanaged resource needs no finalizer:
sealed class Label
{
public string Text { get; }
public Label(string text) { Text = text; }
}
For an owned disposable resource, follow the separate disposal pattern rather than copying this resource-free class.
Regression checks¶
Review whether a finalizer is needed at all. Test deterministic disposal through a fake owned resource, including repeated disposal. Do not rely on forcing garbage collection as the normal cleanup mechanism or throw from a production finalizer to test error handling.