पाठ 19 / 25
Garbage Collection and IDisposable
Explain how the GC works and release unmanaged resources with using.
Automatic memory, manual resources
The .NET garbage collector (GC) frees heap memory that is no longer reachable from roots (static fields, local variables on thread stacks, CPU registers). It is generational: new objects start in generation 0, which is collected often and cheaply; survivors are promoted to gen 1 and then gen 2, collected less often. Objects of 85,000 bytes or more go to the large object heap. Most short-lived objects die young, so gen 0 collections are fast. The GC manages memory only. Files, sockets, database connections and OS handles are unmanaged resources that must be released promptly, which is what IDisposable is for. A using declaration or using block calls Dispose() automatically, even if an exception is thrown; IAsyncDisposable with await using does the same for async cleanup. Finalizers exist for last-resort cleanup of raw handles, but you rarely write one; wrap handles in SafeHandle instead.
Generations of the managed heap
Most objects die young in generation 0; long-lived survivors move to older generations.
Deterministic cleanup with using
Both the file and the connection are closed even if an exception occurs.
using var writer = new StreamWriter("report.csv"); // disposed at end of scope
writer.WriteLine("id,total");
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
public sealed class TempFile : IDisposable
{
public string Path { get; } = System.IO.Path.GetTempFileName();
private bool _disposed;
public void Dispose()
{
if (_disposed) return;
File.Delete(Path);
_disposed = true;
}
}Do not dispose HttpClient per request
HttpClient is the famous exception: creating and disposing one per request can exhaust sockets. Reuse a long-lived instance or use IHttpClientFactory in ASP.NET Core.
त्वरित जाँच: What does a `using` declaration guarantee?
- Dispose() is called when the scope ends, even if an exception is thrown
- The object is garbage-collected immediately
- The object is allocated on the stack
- The object becomes thread-safe
Answer
Dispose() is called when the scope ends, even if an exception is thrown — using ensures Dispose runs at the end of scope, releasing resources deterministically.