Skip to main content
2 of 6
added an autodispose for `IDisposable` types.
Jesse C. Slicer
  • 14.2k
  • 1
  • 39
  • 52

It's a little difficult to give a full review without the removed null checks, but I'll give an observation:

In Dispose(), you depend on null to be the value of _state to judge whether or not to call the cleanup action. That's all well and good, but you should likely then constrain the generic parameter T to be class

class Usingifier<T> : IDisposable where T : class

You also have an issue with multiple-disposals calling the cleanup action with the state - both probably being stale after the fact. The class should be considered unusable after the cleanup. Or at least unusable until the initialize function has been called again. Simple boolean should take care of that:

class Usingifier<T> : IDisposable where T : class
{
    private readonly Func<T> _initialize;

    private readonly Action<T> _cleanUp;

    private bool _disposed;

    private T _state;

    public Usingifier(Func<T> initialize, Action<T> cleanUp)
    {
        _initialize = initialize;
        _cleanUp = cleanUp;
    }

    public Usingifier<T> Initialize()
    {
        _state = _initialize();
        _disposed = false;
        return this;
    }

    public virtual void Dispose()
    {
        if (_disposed)
        {
            throw new ObjectDisposedException(null, "Object has been cleaned up.");
        }

        _disposed = true;

        if (_state != null)
        {
            _cleanUp(_state);
        }
    }
}

You may want to also put in some sort of nice (optional) automatic disposal if T itself happens to be IDisposable. Here's a quick take on that:

class Usingifier<T> : IDisposable where T : class
{
    private readonly T _object;

    private readonly Func<T> _initialize;

    private readonly Action<T> _cleanUp;

    private readonly bool _autoDispose;

    private bool _disposed;

    private T _state;

    public Usingifier(Func<T> initialize, Action<T> cleanUp, T @object = null, bool autoDispose = false)
    {
        _initialize = initialize;
        _cleanUp = cleanUp;
        _object = @object;
        _autoDispose = autoDispose;
    }

    public Usingifier<T> Initialize()
    {
        _state = _initialize();
        _disposed = false;
        return this;
    }

    public virtual void Dispose()
    {
        if (_disposed)
        {
            throw new ObjectDisposedException(null, "Object has been cleaned up.");
        }

        _disposed = true;

        if (_state != null)
        {
            _cleanUp(_state);
        }

        if (_autoDispose)
        {
            var @object = _object as IDisposable;

            if (@object != null)
            {
                @object.Dispose();
            }
        }
    }
Jesse C. Slicer
  • 14.2k
  • 1
  • 39
  • 52