Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a Task<TDerived> to a Task<TBase>?

Since C#'s Task is a class, you obviously can't cast a Task<TDerived> to a Task<TBase>.

However, you can do:

public async Task<TBase> Run() {     return await MethodThatReturnsDerivedTask(); } 

Is there a static task method I can call to get a Task<TDerived> instance which essentially just points to the underlying task and casts the result? I'd like something like:

public Task<TBase> Run() {     return Task.FromDerived(MethodThatReturnsDerivedTask()); } 

Does such a method exist? Is there any overhead to using an async method solely for this purpose?

like image 922
ChaseMedallion Avatar asked Mar 20 '13 17:03

ChaseMedallion


1 Answers

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; } 
like image 97
Stephen Cleary Avatar answered Sep 21 '22 13:09

Stephen Cleary