DI008

Disposable Transient Service

transient services implementing `IDisposable`/`IAsyncDisposable` in risky patterns.

Default severity: Warning · Code fix: Yes

Why it matters

disposal ownership can become unclear and resources may be leaked.

Borrowing a bike every minute without returning the old one fills the whole bike shed.

README problem example

services.AddTransient<IMyService, DisposableService>();

public sealed class DisposableService : IMyService, IDisposable
{
    public void Dispose() { }
}

README better pattern

services.AddScoped<IMyService, DisposableService>();
// or ensure explicit disposal ownership if transient is intentional

Yes. Suggests safer lifetime alternatives.

Repo sample extraction

Examples pulled from the sample app

Open full sample file

Sample app warning case

public class BadDisposableTransient : IDisposableService, IDisposable
{
    private bool _disposed;

    public void DoWork()
    {
        if (_disposed) throw new ObjectDisposedException(nameof(BadDisposableTransient));
        // Do work...
    }

    public void Dispose()
    {
        _disposed = true;
        // Resources will NOT be cleaned up because container doesn't track transients
    }
}

Sample app safe pattern

public class GoodScopedDisposable : IScopedDisposable
{
    private bool _disposed;

    public void DoWork()
    {
        if (_disposed) throw new ObjectDisposedException(nameof(GoodScopedDisposable));
        // Do work...
    }

    public void Dispose()
    {
        _disposed = true;
        // Container WILL call this when the scope is disposed
    }
}