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?
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;
}