Glossary / IDisposable
IDisposable
IDisposable defines deterministic synchronous cleanup through Dispose(). Types implement it when they own resources or other disposable objects that should be released promptly; consumers normally call it with using or using declarations.
Ownership and implementation
A type should dispose resources it owns, not arbitrary borrowed dependencies unless ownership is explicit. Disposal should be idempotent where practical, release managed disposable members and directly owned native resources, and leave the object unusable or clearly defined afterward. If a type owns a SafeHandle, disposing that handle is generally preferred to writing a finalizer. A finalizer is only a fallback for direct unmanaged ownership.
The dispose pattern may use a protected virtual Dispose(bool) in inheritable classes; sealed types can use a simpler pattern. GC.SuppressFinalize(this) is needed when a finalizer exists and deterministic disposal has completed. Avoid resurrecting resources or throwing during routine disposal. If cleanup can fail, document behavior and consider how it interacts with other cleanup in a using scope.
Async cleanup
If release requires asynchronous I/O, implement IAsyncDisposable and support await using; some types implement both interfaces. Synchronous Dispose should not block on async cleanup unless the API explicitly defines that compromise.
Interview questions
- What does IDisposable provide? Deterministic synchronous resource release.
- Who should a type dispose? Resources it owns, according to explicit ownership contract.
- When use a finalizer? Rarely, for direct unmanaged-resource fallback; SafeHandle is preferred.
- What does
GC.SuppressFinalizedo? Prevents finalizer processing after successful deterministic cleanup. - When implement IAsyncDisposable? When cleanup naturally requires asynchronous operations.