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: 273
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