Search code examples
c#.netgarbage-collectionfinalizer

IDisposable Pattern. How does my finalizer's call of dispose ever free managed resources?


I have Class A that implements the Disposable pattern in order to release unmanaged resources such as unsubscribing from events. Class B uses Class A, but does not wrap it in a using {..} block nor explicity calls A.Dispose(true) so A.dispose is called in A's finalizer via the standard Dispose(false) call. But then by setting the bool parameter to false, the unmanaged resources will not be cleaned up, i.e not unsubscribing from subscribed events. Shouldn't the finalizer be calling Dispose(true) or should Class B explicitly call A.Dispose(true) at some point such as in its own finalizer?

private bool _disposed = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _promotionsSQLTableDependency.Stop();
                _awardsSQLTableDependency.Stop();
                _progressiveGeneratorService.OnProgressiveLevelsUpdate -= _progressiveUpdateHandler;
            }

            _disposed = true;
        }
    }

    ~PromotionHandler()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

Solution

  • implements the Disposable pattern in order to release unmanaged resources such as unsubscribing from events.

    Unsubscribing from an event isn't an unmanaged resource that needs to be cleaned up though.

    Class B uses Class A, but does not wrap it in a using {..} block nor explicity calls A.Dispose(true)

    You should treat that as a bug in your program. The whole point of implementing IDisposable is because that object needs to be explicitly cleaned up with the owner(s) are finished with it.

    But then by setting the bool parameter to false, the unmanaged resources will not be cleaned up,

    But those aren't unmanaged resources, which is why they aren't cleaned up in the finally block.

    Shouldn't the finalizer be calling Dispose(true) or should Class B explicitly call A.Dispose(true) at some point such as in its own finalizer?

    No. You shouldn't be interacting with managed objects in the finalizer. It's not safe to do so. Since you have no unmanaged resources to clean up in a finalizer, you shouldn't even have a finalizer.