Dispose, when is it called?
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
Dispose is not called by the garbage collector just because an object became unreachable. In .NET, Dispose is part of an explicit resource-management protocol, and it runs when your code, a using statement, or a framework owner deliberately calls it.
What Dispose Is For
Managed memory is reclaimed by the garbage collector, but unmanaged or scarce resources still need prompt cleanup. Examples include:
- file handles
- database connections
- sockets
- timers
- native handles
That is why types implement IDisposable.
Implementing IDisposable does nothing by itself. The method still has to be called.
using Calls Dispose
The most common answer to "when is it called?" is: at the end of a using scope.
At the end of that scope, the compiler-generated code calls Dispose for you, even if an exception occurs inside the block.
Equivalent expanded shape:
That is the most important mental model.
Explicit Calls Also Count
You can call Dispose directly.
This works, but using is safer because it guarantees cleanup in the presence of exceptions.
In async code, use await using for types that implement IAsyncDisposable.
That is a different protocol from IDisposable, but the same ownership principle applies.
The Garbage Collector Does Not Automatically Call Dispose
This is the part people often get wrong. If an object is collected, its memory may be reclaimed, but Dispose is not invoked automatically unless some surrounding code chose to call it.
Finalizers are a separate mechanism:
A finalizer is not the same as Dispose:
- it runs nondeterministically
- it may run much later
- it exists mainly as a safety net for unmanaged cleanup
Well-behaved disposable types still expect callers to dispose them explicitly.
Dependency Injection Containers May Dispose for You
In ASP.NET Core and other DI-based frameworks, container-managed services are disposed automatically when their owning scope ends.
Typical examples:
- scoped services disposed at the end of the request
- singleton services disposed when the host shuts down
That means you should not manually dispose services you did not create yourself. Ownership matters.
The rule is simple:
- if your code created it, your code usually disposes it
- if the container created it, let the container manage disposal
Implementing the Pattern Correctly
For most modern code that wraps other disposable resources, a straightforward pattern is enough.
The key point is idempotence. Calling Dispose twice should not break the program.
For low-level types that own native handles directly, the full dispose pattern with SafeHandle or a finalizer may still be appropriate. But most application code does not need to invent finalizers manually.
Common Pitfalls
- Assuming the garbage collector will automatically call
Dispose. - Forgetting that
usingis just compiler-generatedtry/finally. - Manually disposing objects owned by a dependency injection container.
- Confusing finalizers with deterministic disposal.
- Implementing
IDisposablebut never callingDisposeanywhere.
Summary
- '
Disposeruns when code explicitly calls it, directly or throughusing.' - The garbage collector reclaims memory, but it does not guarantee
Disposewill run. - Finalizers are a separate, nondeterministic safety mechanism.
- Ownership determines who is responsible for disposal.
- In normal C# code, prefer
usingorusing varto make disposal reliable.
Related reading
- Disposing WPF User Controls
- DisProving that one algorithm works faster than another due to language internals
- Distribute points on a circle as evenly as possible
- Distributed Hash Tables Preventing nodes from storing petabytes of data?
- Distinct not working with LINQ to Objects
- Distributed caching and locking with Redis in .NET Core
- Distributed Load testing using Gatling tool
- Distributed systems and choosing the nearest datacenter

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.