How do you prevent IDisposable from spreading to all your classes?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
When a class implements IDisposable, every class that owns it must also implement IDisposable, creating a "viral" spread through your codebase. To prevent this, limit IDisposable to the lowest possible level by using dependency injection (let the DI container manage disposal), wrapping disposable resources in using blocks at the point of use, encapsulating disposal behind non-disposable abstractions, or using factory/pool patterns that centralize resource lifecycle management.
The Problem
Strategy 1: Dependency Injection (Best)
Let the DI container manage the disposable object's lifetime:
OrderService depends on ILogger (not IDisposable), so it does not need Dispose().
Strategy 2: using Blocks at the Point of Use
Create and dispose resources locally instead of storing them as fields:
DataExporter does not hold a SqlConnection as a field, so it does not need IDisposable.
Strategy 3: Factory Pattern
Delegate resource creation to a factory that the caller disposes:
The factory itself is not IDisposable — only the connections it creates are.
Strategy 4: Encapsulate Behind a Non-Disposable Wrapper
Hide the disposable resource behind a wrapper that manages its own lifecycle:
Strategy 5: Object Pool
For expensive disposable resources, pool them instead of creating/disposing per use:
When IDisposable Should Spread
Not all spreading is bad. If a class truly owns a disposable resource (exclusively responsible for its lifetime), it should implement IDisposable:
The goal is not to eliminate IDisposable entirely, but to push it down to the smallest scope possible.
Common Pitfalls
- Making every class
IDisposablejust because it uses a disposable dependency: Only implementIDisposableif the class owns (creates and is responsible for) the disposable resource. If a dependency is injected, the injector is responsible for disposal, not the consumer. - Storing
HttpClientas a disposable field:HttpClientis designed to be reused and should not be created/disposed per request. UseIHttpClientFactoryin ASP.NET Core, which managesHttpClientlifetimes and pooling without requiring your classes to beIDisposable. - Implementing
IDisposablewithout the full dispose pattern: If your class has a finalizer or is intended for inheritance, implement the full dispose pattern withDispose(bool disposing)andGC.SuppressFinalize. For sealed classes with only managed resources, a simpleDispose()is sufficient. - Forgetting to dispose injected resources when the container does not manage them: If you manually create a disposable object outside a DI container, someone must dispose it. Unmanaged resources leak silently — there is no compiler warning for undisposed objects.
- Using
Disposefor application logic (not just cleanup):Disposeshould only release resources (close files, connections, handles). Do not put business logic like "save final state" or "send shutdown notification" inDispose— it may not be called if an exception occurs before theusingblock completes.
Summary
- Use dependency injection to let the DI container manage disposable lifetimes
- Prefer
usingblocks at the point of use instead of storing disposable fields - Hide disposable resources behind non-disposable interfaces or wrappers
- Use factory patterns so callers create and dispose resources locally
- Only implement
IDisposablewhen your class truly owns the resource
Related reading
- How do you use a Bidirectional BFS to find the shortest path?
- How do you use freeze_graph.py in Tensorflow?
- How does a sorting network beat generic sorting algorithms?
- How does Distributed Shared Memory work in the presence of cache and registers?
- How do you share code between projects/solutions in Visual Studio?
- How do you simulate Mouse Click in C?
- How does docker image size impact runtime characteristics?
- How does Git save space and is fast at the same time?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.