It would be useful if the analyser warned of a code smell when code to return a Task or a Task is embedded inside a try {} block. In such cases, any exceptions in the asynchronous task are not caught which is probably not the programmers intention, and can lead to bugs easily missed during code review.
An example of a suspect block of code would be:
async Task Bar()
{
//Do something async here
}
Task Foo()
{
try
{
return Bar();
}
catch
{
//Handle exception here
return Task.CompletedTask;
}
}
The suggested alternative would be:
async Task Foo()
{
try
{
return await Bar().ConfigureAwait(false);
}
catch
{
//Handle exception here
}
}
A second alternative could be written for the case where programmer did truly mean to only catch exceptions during the creation of the task as a means of avoiding having to suppress the rule and make their intention more explicit:
Task Foo()
{
Task result;
try
{
result = Bar();
}
catch
{
//Handle exception here
result = Task.CompletedTask;
}
return result;
}
The trigger conditions for the rule would be:
- Method return type is Task or Task<T>
- Method is not declared async
- A return statement appears in a try {} block
- The right hand side of the return statement is not one of the methods of the Task object such as FromResult or CompletedTask that do not run asynchronously
The rule would apply to lambda functions as well as named method. A more complex version could check for returning tuples or complex types that contain Task objects, but the simple version would catch the vast majority of mistakes.