.NET › Dependency Injection
How does the DI container's disposal behavior work for IDisposable and IAsyncDisposable services across different lifetimes?
AdvancedAnswer
The DI container automatically tracks and disposes any IDisposable/IAsyncDisposable service it created, calling Dispose/DisposeAsync when the owning scope ends (for Scoped/Transient services resolved within a request scope) or when the application shuts down (for Singleton services) -- notably, Transient services are still tracked and disposed by their containing scope, not immediately after use, which can cause unexpected memory retention if many short-lived Transient disposables accumulate within one long-lived scope.
public class ReportExporter : IDisposable {
public void Dispose() => Console.WriteLine("Disposed");
}
builder.Services.AddTransient<ReportExporter>();
// Even though Transient, if resolved many times within one request scope,
// ALL instances are held and disposed together only when that request scope endsReal-world example A memory profiling session reveals unexpectedly high memory retention within long request scopes traced to hundreds of Transient IDisposable service instances all being held alive until the scope's end rather than being freed immediately after each use.