3

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...

2 Answers2

4

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;
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Should this be in a separate class or in the context file? We have only one context and are calling different database tables in each class. – Emilija Vilija Trečiokaitė Sep 17 '21 at 10:16
  • @EmilijaVilijaTrečiokaitė in the version of the code in the question: you disposed the context in this type - I'm simply preserving that exact same semantic from your original question, but: with simpler code; any questions about lifetimes are entirely up to you and your design - I haven't changed that in any way; the code I've posted would simply be a replacement for where-ever your code currently appears – Marc Gravell Sep 17 '21 at 10:19
1

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).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900