How to convert a Task to a Task?

Does such a method exist?

No.

Is there any overhead to using an async method solely for this purpose?

Yes. But it’s the easiest solution.

Note that a more generic approach is an extension method for Task such as Then. Stephen Toub explored this in a blog post and I’ve recently incorporated it into AsyncEx.

Using Then, your code would look like:

public Task<TBase> Run()
{
  return MethodThatReturnsDerivedTask().Then(x => (TBase)x);
}

Another approach with slightly less overhead would be to create your own TaskCompletionSource<TBase> and have it completed with the derived result (using TryCompleteFromCompletedTask in my AsyncEx library):

public Task<TBase> Run()
{
  var tcs = new TaskCompletionSource<TBase>();
  MethodThatReturnsDerivedTask().ContinueWith(
      t => tcs.TryCompleteFromCompletedTask(t),
      TaskContinuationOptions.ExecuteSynchronously);
  return tcs.Task;
}

or (if you don’t want to take a dependency on AsyncEx):

public Task<TBase> Run()
{
  var tcs = new TaskCompletionSource<TBase>();
  MethodThatReturnsDerivedTask().ContinueWith(t =>
  {
    if (t.IsFaulted)
      tcs.TrySetException(t.Exception.InnerExceptions);
    else if (t.IsCanceled)
      tcs.TrySetCanceled();
    else
      tcs.TrySetResult(t.Result);
  }, TaskContinuationOptions.ExecuteSynchronously);
  return tcs.Task;
}

Leave a Comment