title: Design polymorphism without downcasting
body: <p>I have a class which works with a hardware device. This device supports a number of commands, and I want to implement a common <em>SendCommand</em> function. Commands might or might not have input parameters and/or output result. </p>
  
  <p>What I can do is to write an abstract command type class, and a number of derived command type classes. Those derived classes would actually be different with those input/output specifics of commands. </p>
  
  <p>Now I want <code>SendCommand</code> to return a <code>Task&lt;SpecificCommandType&gt;</code>, that is, task of derived class, but with current design I can only return <code>Task&lt;BaseCommandType&gt;</code>.</p>
  
  <p>I will explain with simple skeleton code:  </p>
  
  <p>Classes:</p>
  
  <pre><code>public abstract class BaseCommandType { ... }
  
  public class CommandType1 : BaseCommandType {
      TaskCompletionSource&lt;CommandType1&gt; Tcs;
  }
  
  public class CommandType2 : BaseCommandType {
      TaskCompletionSource&lt;CommandType2&gt; Tcs;
  }
  </code></pre>
  
  <p>My function:</p>
  
  <pre><code>public Task&lt;T&gt; SendCommand&lt;T&gt;(BaseCommandType type) where T : BaseCommandType {
      ...
      // if I implement TaskCompletionSource&lt;BaseCommandType&gt; Tcs
      // in abstract class, then I can return type.Tcs.Task, and remove
      // generics.
      // But how can I return Task&lt;T&gt;? 
  }
  </code></pre>
  
  <p>I was planned to use this func like this:</p>
  
  <pre><code>CommandTypeX cmd = new CommandTypeX(...);
  SendCommand&lt;CommandTypeX&gt;(cmd).ContinueWith(t =&gt; {
      // access some specifics of t.Result as CommandTypeX
  });
  </code></pre>
  
  <p>How should I design my classes to be able to return <code>Task&lt;CommandTypeX&gt;</code>?  </p>
  
  <p>Or is there a better way to do something I need (without downcast)? </p>
  
  <p><strong>Update1</strong>:
  To be more precise, I can do it like this with downcast (can do I, isn't it?):</p>
  
  <pre><code>public abstract class BaseCommandType {
      public TaskCompletionSource&lt;BaseCommandType&gt; Tcs;
  }
  
  public class CommandTypeX : BaseCommandType { }
  
  public Task&lt;BaseCommandType&gt; SendCommand(BaseCommandType type) {
      ...
      return type.Tcs.Task;
  }
  
  // when task finishes:
  type.Tcs.SetResult(type); // where type is actually of CommandTypeX
  
  // usage:
  CommandTypeX cmd = new CommandTypeX(...);
  SendCommand(cmd).ContinueWith(t =&gt; {
      CommandTypeX command = t.Result as CommandTypeX;
      if (command != null) ...
  });
  </code></pre>
  
  <p>But that's exactly what I want to avoid in first place.</p>
  
  <p><strong>Update2</strong>:
  I think I found another way of going, but still looks not well for me.</p>
  
  <pre><code>public abstract class BaseCommandType {
      internal abstract void SetTcs&lt;T&gt;(TaskCompletionSource&lt;T&gt; tcs);
      internal abstract void HandleData(byte[] data);
  }
  
  public class CommandType1 : BaseCommandType {
      private TaskCompletionSource&lt;CommandType1&gt; _tcs1 = new TaskCompletionSource&lt;CommandType1&gt;();
      public string Data1;
  
      internal override void SetTcs&lt;T&gt;(TaskCompletionSource&lt;T&gt; tcs)
      {
          _tcs1 = tcs as TaskCompletionSource&lt;CommandType1&gt;;
      }
  
      internal override void HandleData(byte[] data)
      {
          // Data1 = someFuncOn(data)
          _tcs1.TrySetResult(this);
      }
  }
  
  public class CommandType2 : BaseCommandType {
      private TaskCompletionSource&lt;CommandType2&gt; _tcs2 = new TaskCompletionSource&lt;CommandType2&gt;();
      public int[] Data2;
  
      internal override void SetTcs&lt;T&gt;(TaskCompletionSource&lt;T&gt; tcs)
      {
          _tcs2 = tcs as TaskCompletionSource&lt;CommandType2&gt;;
      }
  
      internal override void HandleData(byte[] data)
      {
          // Data2 = someFuncOn(data)
          _tcs2.TrySetResult(this);
      }
  }
  
  public class Device {
      private List&lt;BaseCommandType&gt; _commandList = new List&lt;BaseCommandType&gt;();
  
      public Task&lt;T&gt; SendCommand&lt;T&gt;(T t) where T : BaseCommandType
      {
          TaskCompletionSource&lt;T&gt; tcs = new TaskCompletionSource&lt;T&gt;();
          t.SetTcs&lt;T&gt;(tcs);
          _commandList.Add(t);
  
          // later in other thread then device answers
          // locate command in list
          // BaseCommandType c = _commandList[some index];
          // _commandList.RemoveAt(some index);
          // c.HandleData(null);
  
          return tcs.Task;
      }
  }
  
  // usage like this:
  CommandType2 command = new CommandType2();
  device.SendCommand&lt;CommandType2&gt;(command).ContinueWith(t =&gt;
          {
              CommandType2 command2 = t.Result;
              // use command2.Data2 here;
          });
  </code></pre>
  
  <p>Is this way better than in update1? At least I can hide the casting logic inside the library so externally everything would be type safe and robust.
  Or how can I further improve on this?</p>