Should I use IDisposable for purely managed resources?

Posted by John Gietzen on Stack Overflow See other posts from Stack Overflow or by John Gietzen
Published on 2010-04-05T20:08:10Z Indexed on 2010/04/05 20:13 UTC
Read the original article Hit count: 249

Filed under:
|
|
|
|

Here is the scenario:

I have an object called a Transaction that needs to make sure that only one entity has permission to edit it at any given time.

In order to facilitate a long-lived lock, I have the class generating a token object that can be used to make the edits.

You would use it like this:

var transaction = new Transaction();

using (var tlock = transaction.Lock())
{
    transaction.Update(data, tlock);
}

Now, I want the TransactionLock class to implement IDisposable so that its usage can be clear. But, I don't have any unmanaged resources to dispose. however, the TransctionLock object itself is a sort of "unmanaged resource" in the sense that the CLR doesn't know how to properly finalize it.

All of this would be fine and dandy, I would just use IDisposable and be done with it.

However, my issue comes when I try to do this in the finalizer:

    ~TransactionLock()
    {
        this.Dispose(false);
    }

I want the finalizer to release the transaction from the lock, if possible. How, in the finalizer, do I detect if the parent transaction (this.transaction) has already been finalized?

Is there a better pattern I should be using?


The Transaction class looks something like this:

public sealed class Transaction
{
    private readonly object lockMutex = new object();

    private TransactionLock currentLock;

    public TransactionLock Lock()
    {
        lock (this.lockMutex)
        {
            if (this.currentLock != null)
                throw new InvalidOperationException(/* ... */);

            this.currentLock = new TransactionLock(this);
            return this.currentLock;
        }
    }

    public void Update(object data, TransactionLock tlock)
    {
        lock (this.lockMutex)
        {
            this.ValidateLock(tlock);

            // ...
        }
    }

    internal void ValidateLock(TransactionLock tlock)
    {
        if (this.currentLock == null)
            throw new InvalidOperationException(/* ... */);

        if (this.currentLock != tlock)
            throw new InvalidOperationException(/* ... */);
    }

    internal void Unlock(TransactionLock tlock)
    {
        lock (this.lockMutex)
        {
            this.ValidateLock(tlock);

            this.currentLock = null;
        }
    }
}

© Stack Overflow or respective owner

Related posts about c#

Related posts about .NET