Avoid repetitive coding when disposing of objects

With a purpose of memory optimization we've been adding these lines of code:

public class Whatever: IDisposable

private bool disposed = false;

protected virtual void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
            context.Dispose();
        }
    }
    this.disposed = true;
}

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

To every single of our repositories, then are updating tests for each repo as well. I am wondering, since copy+paste isn't really encouraged in coding isn't there a better way to implement this? Especially annoying since, depending on a project, we have 10-40 repositories...

Upvotes: 3

Views: 89

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1064324

To expand on the base-class approach that Franz hints at; something like:

// common base class that handles the shared details
public abstract class MyCommonBase : IDisposable
{
    protected SomeContext Context { get; private set; }

    public MyCommonBase(SomeContext context)
        => Context = context ?? throw new ArgumentNullException(nameof(context));

    public virtual void Dispose()
    {
        // your choice of dispose code here, via Context
    }
}

// specific implementation class
public class MySomething : MyCommonBase
{
    public MySomething(SomeContext context) : base(context) {}

    // your *extra* code here; can read Context from base
}

Note that in MySomething you don't need to deal with any of the disposal bits - that's all handled by the base class (although you can still override the Dispose() method to add additional cleanup features).

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1064324

Perhaps simpler - use the context itself to track disposal:

protected virtual void Dispose(bool disposing)
{
    if (disposing) context?.Dispose();
    context = null;
}

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

Note that I also think it is vanishingly unlikely that you have a finalizer involved here (and if you do, that is probably a big mistake), so honestly: you can simplify further:

public void Dispose()
{
    context?.Dispose();
    context = null;
}

Upvotes: 4

Related Questions