Tom Gullen
Tom Gullen

Reputation: 61725

Is a disposable object in my iDisposable class guaranteed to be released from memory?

Given the following class:

public sealed class DistributedLock : IDisposable
{
    private IRedLock Lock { get; }
    private bool _disposed;

    public DistributedLock(string lockKey, TimeSpan expiry)
    {
        Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);
    }

    private void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (Lock != null)
            {
                Lock.Dispose();
            }
        }

        _disposed = true;
    }

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

    ~DistributedLock()
    {
        Dispose(false);
    }
}

Where IRedLock implements iDisposable, and I use the above class in the following way:

using(new DistributedLock("SomeKey"))
{
    ... do something
}

Will the DistributedLock and contained IRedLock class be released from memory under all circumstances?

Upvotes: 0

Views: 99

Answers (1)

Joel Coehoorn
Joel Coehoorn

Reputation: 415881

IDisposable is about managing resources other than memory: things like GDI handles, sockets, file handles, etc. It does not pre-empt the garbage collector. Therefore, IDisposable will only help you release memory in two situations:

  1. If your IRedLock type acquires unmanaged memory, e.g. via third party library or unsafe code.
  2. If your Dispose() method cleans up references to this object from other objects, to be sure the object will be eligible for garbage collection when it might not have been otherwise (as happens with, for example, event handlers).

If neither of those two apply (and nothing in the code above indicates they do), you don't gain anything from IDisposable in terms of memory management.

What you might get from IDisposable in this code is a better mechanism to release the connection hinted at in this line:

Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);

However, you probably don't need the associated finalizer. You're only wrapping something else that already has a finalizer, and therefore you can use a simpler IDisposable pattern without the extra complexity:

public sealed class DistributedLock : IDisposable
{
    private IRedLock Lock { get; }

    public DistributedLock(string lockKey, TimeSpan expiry)
    {
        Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);
    }

    public void Dispose()
    {
        Lock?.Dispose();
    }
}

Upvotes: 1

Related Questions