user2608601
user2608601

Reputation: 147

AddSingleton - lifetime - does class need to implement IDisposable?

When using DI for services added using AddScoped or AddSingleton, does the service need to implement IDisposable (even if it is not using any unmanaged resources like files)?

Found below sample from Microsoft Docs:

// Services that implement IDisposable:
public class Service1 : IDisposable {}
public class Service2 : IDisposable {}
public class Service3 : IDisposable {}

public interface ISomeService {}
public class SomeServiceImplementation : ISomeService, IDisposable {}

public void ConfigureServices(IServiceCollection services)
{
    // The container creates the following instances and disposes them automatically:
       services.AddScoped<Service1>();
       services.AddSingleton<Service2>();
       services.AddSingleton<ISomeService>(sp => new SomeServiceImplementation());

    // The container doesn't create the following instances, so it doesn't dispose of
    // the instances automatically:
       services.AddSingleton<Service3>(new Service3());
       services.AddSingleton(new Service3());
}

What happens if I have this code:

public class Service0  // (doesn't implement Disposable) 

services.AddScoped<Service0>();   // what happens to it when request scope ends? Does it stay on the heap?

services.AddSingleton<Service0>();   // it lives till application dies
services.AddSingleton(new Service0());  // ??
services.AddSingleton<IConfigureOptions<Service0>>((ctx) =>
   {
          return new ConfigureNamedOptions<Service0>(null, (config) =>
   {
// Do something here -- in debug mode it is executing this logic for each request
}}  // it is returning "new Service0" when a request is made. Does it mean for each request it returns new object and keeps in heap memory or returns same previously created object?

Upvotes: 3

Views: 2303

Answers (2)

felix-b
felix-b

Reputation: 8498

does the service need to implement IDisposable(even if it is not using any unmanaged resources like files)

Usually it doesn't, because the primary purpose of IDisposable is allow releasing unmanaged resources. However, there is an additional reason for implementing IDisposable. The Dispose() method is sometimes used as a hook for completing actions started in the constructor. For example, a constructor starts duration measurement, while Dispose() stops the measurement and reports the duration to some monitoring mechanism.

A little of backgroiund about IDisposable

If an object doesn't implement IDisposable it doesn't mean it stays in heap. In fact, the GC doesn't even know what IDisposable is. This interface is only a pattern. However, the compiler knows IDisposable, and it emits calls to Dispose() in the end of using statement scope.

In addition, in many cases infrastructure layers or libraries (such as DI in ASP.NET Core) check if an object implements IDisposable, and if it does, call Dispose() on it.

So the fact that an object implements IDisposable doesn't by itself guarantee that Dispose() will be called before GC. It depends on the users of the object. To actually ensure Dispose() before GC, the full implementation of the disposable pattern includes calling Dispose() from the "destructor".

what happens to it when request scope ends? stays in heap? what happens to it when request scope ends?

  • AddScoped<Service0>(): at the end of the request, the reference to the object is "forgotten" (the GC is free to remove it at any moment). Just prior to forgetting the reference, the object is checked for whether it implements IDisposable, and if it does, Dispose() will be called on it.

  • AddSingleton<Service0>(): at the end of the web host lifetime, the reference to the object is "forgotten" (the GC is free to remove it at any moment). Just prior to forgetting the reference, the object is checked for whether it implements IDisposable, and if it does, Dispose() will be called on it.

  • AddSingleton(new Service0()): at the end of the web host lifetime, the reference to the object is "forgotten" (the GC is free to remove it at any moment). But since this object was supplied from the outside and not instantiated by the DI, it won't be checked for IDisposable and the Dispose won't be called.

Upvotes: 6

Ali Alp
Ali Alp

Reputation: 731

IDisposable is just an interface which give the implementer class the chance to do some cleanup on object destruction , it does not do anything by itself. DI will destroy the instances depends on their lifetime like scoped , transient , Singleton, will the object exists after destruction on the heap is the Gorbagge Collector's duty to decide . If you define a new instace inside a Singleton that object will be destroyed with the Singleton instace and due to lifetime of the Singleton which is till the end of the application's lifetime therefore it will follow it's parent's lifetime , except if you do some unmanaged operation there.

Upvotes: 0

Related Questions