title: Subclassing all classes in a 'chain' of subclasses
body: <p>I came up with this example to clarify my question</p>
  
  <p>We start with a base class</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Just a silly example class
  /// &lt;/summary&gt;
  class CFileStream
  {
      protected readonly string FilePath;
  
      public CFileStream(string filePath)
      {
          FilePath = filePath;
      }
  
      public virtual void Write(string s)
      {
          var stream = GetStream(FilePath);
          //etc
      }
  
      /// &lt;summary&gt;
      /// Take filePath as an argument to make subclassing easier
      /// &lt;/summary&gt;
      protected virtual FileStream GetStream(string filePath)
      {
          return new FileStream(filePath, FileMode.OpenOrCreate);
      }
  }
  </code></pre>
  
  <p>Create a subclass for it</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Building on top of CFileStream, created an encrypted version
  /// &lt;/summary&gt;
  class CFileStreamEncrypted : CFileStream
  {
      private readonly string _key;
  
      public CFileStreamEncrypted(string filePath, string key):base(filePath)
      {
          _key = key;
      }
  
      /// &lt;summary&gt;
      /// For added complexity, let's also wrap a possible excepton
      /// &lt;/summary&gt;
      public override void Write(string s)
      {
          try
          {
              base.Write(s);
          }
          catch (ImaginaryCryptoException ex)
          {
              throw new ImaginaryCustomException("bladibla", ex);
          }
      }
  
      /// &lt;summary&gt;
      /// Wrap the base stream in an imaginary crypto class
      /// &lt;/summary&gt;
      protected override FileStream GetStream(string filePath)
      {
          return new CImaginaryCryptoStream(base.GetStream(filePath), _key);
      }
  }
  </code></pre>
  
  <p>Now we wish to create a second subclass, but one that works with the initial filewriter as well as the encrypted version.</p>
  
  <p>The first one makes sense</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Building on top of CFileStream, created an auto-split version
  /// &lt;/summary&gt;
  class CFileStreamSplit : CFileStream
  {
      public CFileStreamSplit(string filePath) 
          : base(filePath)
      {
      }
  
      protected int Counter;
  
      /// &lt;summary&gt;
      /// Close stream and move to next file at the appropriate time(s)
      /// &lt;/summary&gt;
      public override void Write(string s)
      {
          do
          {
              Stream stream;
              if (ImaginaryBooleanMustSplit)
                  stream = GetStream(FilePath);
              //etc
          } while (ImaginaryBooleanDataLeftToWrite);
      }
  
      /// &lt;summary&gt;
      /// Get base stream but with altered filePath
      /// &lt;/summary&gt;
      protected override FileStream GetStream(string filePath)
      {
          return base.GetStream(GetNextpath(filePath));
      }
  
      /// &lt;summary&gt;
      /// Ignore proper extension / file-exists etc.
      /// &lt;/summary&gt;
      protected virtual string GetNextpath(string filePath)
      {
          return filePath + ++Counter;
      }
  }
  </code></pre>
  
  <p>The second one (below this) is completely duplicate code, except for the constructor which now also requires the encryption key.</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Build the same auto-split version but this time on top of the encrypted subclass
  /// &lt;/summary&gt;
  class CFileStreamSplitEncrypted : CFileStreamEncrypted
  {
      public CFileStreamSplitEncrypted(string filePath, string key)
          : base(filePath, key)
      {
      }
  
      /*
       * Note that there are no changes below this line
       */
  
      protected int Counter;
  
      /// &lt;summary&gt;
      /// Close stream and move to next file at the appropriate time(s)
      /// &lt;/summary&gt;
      public override void Write(string s)
      {
          do
          {
              Stream stream;
              if (ImaginaryBooleanMustSplit)
                  stream = GetStream(FilePath);
              //etc
          } while (ImaginaryBooleanDataLeftToWrite);
      }
  
      /// &lt;summary&gt;
      /// Get base stream but with altered filePath
      /// &lt;/summary&gt;
      protected override FileStream GetStream(string filePath)
      {
          return base.GetStream(GetNextpath(filePath));
      }
  
      /// &lt;summary&gt;
      /// Ignore proper extension / file-exists etc.
      /// &lt;/summary&gt;
      protected virtual string GetNextpath(string filePath)
      {
          return filePath + ++Counter;
      }
  }
  </code></pre>
  
  <p>There are of course a lot of ways to reduce the amount of duplicate code here, but I have yet to find 'the best' way, if there even is such a thing. So; what is the least time-consuming, cleanest, most flexible way to get a round this issue in your opinion/experience?</p>