title: How to generalize two classes
body: <p>How I can combine <code>class A</code> and <code>class B</code> into for example single generic class</p>
  
  <pre><code>public interface IA { }
  public interface IB { }
  
  public class A : IA, IDisposable
  {
      public void Clear()
      {
      }
  
      protected virtual void Dispose(bool disposing)
      {
          if (disposing)
          {
              //logic
          }
      }
  
      public void Dispose()
      {
          Dispose(true);
          GC.SuppressFinalize(this);
      }
  }
  
  public class B : IB, IDisposable
  {
      public void Detach()
      {
      }
      protected virtual void Dispose(bool disposing)
      {
          if (disposing)
          {
            //logic
          }
      }
  
      public void Dispose()
      {
          Dispose(true);
          GC.SuppressFinalize(this);
      }
  }
  
  public class BClearIfFail : B
  {
      private readonly Func&lt;bool&gt; _isFailed;
  
      public BClearIfFail(Func&lt;bool&gt; isFailed)
      {
          _isFailed = isFailed;
      }
  
      protected override void Dispose(bool dispose)
      {
          if (dispose)
          {
              if (_isFailed())
              {
                 Detach();
                 return;
              }
          }
  
          base.Dispose(dispose);
      }
  }
  
  public class AClearIfFail : A
  {
      private readonly Func&lt;bool&gt; _isFailed;
  
      public AClearIfFail(Func&lt;bool&gt; isFailed)
      {
          _isFailed = isFailed;
      }
  
      protected override void Dispose(bool dispose)
      {
          if (dispose)
          {
              if (_isFailed())
              {
                  Clear();
                  return;
              }
          }
  
          base.Dispose(dispose);
      }
  }
  </code></pre>
  
  <p>In other words I need something like this:</p>
  
  <pre><code>//not for compile =)
  public class Single&lt;T&gt; : T where T : IDisposable
  {
      private readonly Func&lt;bool&gt; _whenSkip;
      private readonly Action _howToSkip;
  
      public Single(Func&lt;bool&gt; whenSkip, Action howToSkip)
      {
          _whenSkip = whenSkip;
          _howToSkip = howToSkip;
      }
  
      public void Dispose()
      {
          if (_whenSkip())
          {
              Log.Message1(Resources.LogCleanupOfResourcesWillBeSkipped);
              _howToSkip();
              return;
          }
  
          T.Dispose();
      }
  }
  </code></pre>
  
  <p>How I want to use this class in my code:</p>
  
  <pre><code>public static class MyFactory&lt;T&gt;
  {
      public static T Create(bool skipCleanUp, Func&lt;bool&gt; isFailed, Action howToSkip)
      {
          return skipCleanUp ? new Single&lt;T&gt;(isFailed, howToSkip) : new T();
      }
  }
  </code></pre>
  
  <p>And I try to explain context:</p>
  
  <pre><code>public interface IUndoStack
  {
      void Push(Action action);
  }
  
  public class UndoStack : IUndoStack, IDisposable
  {
      private readonly Stack&lt;Action&gt; _undo = new Stack&lt;Action&gt;();
  
      public UndoStack()
      {
      }
  
      public void Push(Action action)
      {
          _undo.Push(action);
      }
  
      public void Clear()
      {
          _undo.Clear();
      }
  
      public void Dispose()
      {
          Dispose(true);
          GC.SuppressFinalize(this);
      }
  
      protected virtual void Dispose(bool dispose)
      {
          if (dispose)
          {
              foreach (var action in _undo)
              {
                  try
                  {
                      action.Call();
                  }
                  catch (Exception e)
                  {
                      Log.Exception(e);
                  }
              }
              _undo.Clear();
          }
      }
  }
  
  //context
  
  private void RestoreDatabase()
  {
      UndoStack undoStack = null;
  
      try
      {
          undoStack = new UndoStack();
          undoStack.Add(DeleteFiles())
          CopyFiles(undoStack);
          undoStack.Clear();
      }
      catch when(SkipCleanUpIfFail)
      {
          //Log
          undoStack?.Clear();
          throw;
      }
      finally
      {
          undoStack?.Dispose();
      }
  }
  </code></pre>