In my current C# project, I have a need to share some IDisposable
objects between various classes of unknown lifetime. After searching the internet without success, I decided to come up with my own Reference Counting implementation using Extension Methods:
using System;
using System.Runtime.CompilerServices;
public static class IDisposableExtensions
{
private class RefCount
{
public int refCount;
}
private static ConditionalWeakTable<IDisposable, RefCount> refCounts =
new ConditionalWeakTable<IDisposable, RefCount>();
public static void Retain(this IDisposable disposable)
{
lock (refCounts)
{
RefCount refCount = refCounts.GetOrCreateValue(disposable);
refCount.refCount++;
}
}
public static void Release(this IDisposable disposable)
{
lock (refCounts)
{
RefCount refCount = refCounts.GetOrCreateValue(disposable);
if (refCount.refCount > 0)
{
refCount.refCount--;
if (refCount.refCount == 0)
{
refCounts.Remove(disposable);
disposable.Dispose();
}
}
else
{
disposable.Dispose();
}
}
}
}
Note that, while this works fine, it is of course a very inefficient implementation of an already inefficient mechanism. Luckily, there are likely only a handful of objects requiring this. Use using{}
blocks whenever you can! Also, always consider whether it is worth the extra hassle of using explicit reference-counting, or whether you would be better off just letting the garbage collector handle the cleanup. If disposable objects are well written, they will have a destructor as well.
The nice thing is, however, that it works with any old IDisposable
implementing object, regardless of its origin (as long as it hasn't been casted to Object
, of course).
Warning: Newly created objects don't automatically get a refcount
of 1
, as you might expect. Rather, if you want to use reference counting on any object, you'll have to call Retain()
explicitly. Also, all the usual advice around reference-counted objects apply, i.e., don't create reference loops.
Update: Updated the code and text to incorporate some of Paulo Zemek's excellent feedback. His comment seems to have vanished, but thanks anyway!
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.