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
innerTaskis 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
onErrorTaskFactorywill 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.


