Example with return innerTask.Result
:
CodePudding user response:
What possible benefit is there from using
return await Task.FromResult<T>(innerTask.Result)
as opposed to justreturn innerTask.Result
?
Absolutely zero benefit. That's the kind of code that your end up writing when you are struggling with a concept that you don't fully understand, and you reach to a version that compiles and works correctly. Your code might end up decorated with some useless cargo, which nonetheless is not harmful, so it might survive multiple code reviews and revisions.
Here is a better way to write the Otherwise
extension method:
public static Task<T> Otherwise<T>(this Task<T> task, Func<Task<T>> one rrorTaskFactory)
{
return task.ContinueWith(innerTask =>
{
if (innerTask.IsFaulted) return one rrorTaskFactory();
return innerTask;
}, default, TaskContinuationOptions.DenyChildAttach |
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default).Unwrap();
}
Notice that the continuation is not async
, and it returns the innerTask
, not its result. With this version you get these benefits:
- In case the
onErrorTaskFactory()
returns a Task that also fails, and it contains more that one exceptions (think of passing a lambda that returnTask.WhenAll()
), all the errors will be propagated, not just the first one. - In case the
innerTask
is canceled, the cancellation will be propagated without an additional internaltry
/catch
. Throwing and catching exceptions in C# is quite expensive. - The code complies with the CA2008 guideline ("Do not create tasks without passing a TaskScheduler").
- The
onErrorTaskFactory
will be invoked synchronously on the thread that completed theinnerTask
, avoiding a thread-switch.
These benefits are not ground-breaking. I would evaluate the original implementation in the book as quite decent. It doesn't have any terrible bugs or inefficiencies.