पाठ 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.

Three horizontal bands from small and busy to large and calm, with many small dots in the first band fading out and a few dots moving down into the later bands.
Figure 7.1 — Gen 0, gen 1 and gen 2, with promotion of survivors.

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.