-
Notifications
You must be signed in to change notification settings - Fork 482
Description
Describe the problem you are trying to solve
What I see often in code written by developers who are not completely familiar with how async/await works is the following pattern:
public async Task RunAsync() {
await DoSomethingAsync();
}or
public async Task<int> RunAsync() {
if(new Random().Next() % 2 == 0) {
return await GetValueAsync();
}
return await GetOtherValueAsync();
}These methods can be optimized to return the Tasks directly without a need for awaiting them:
public Task RunAsync() {
return DoSomethingAsync();
}and
public Task<int> RunAsync() {
if(new Random().Next() % 2 == 0) {
return GetValueAsync();
}
return GetOtherValueAsync();
}respectively. This prevents the compiler from creating an unnecessary state machine and can delegate awaiting to the caller.
I am proposing an Analyzer with the "Info" severity which analyzes methods, local functions and lambdas and can report when a Task can be returned directly instead of awaiting it.
Describe suggestions on how to achieve the rule
I have a pretty solid Analyzer + CodeFix implemented already. It targets methods, local functions and lambdas, checks if the return type is Task or Task<T> and then acts accordingly.
For a Task-returning method, an await expression must either immediately be followed by a return; or must be the last statement in the body.
For a Task<T>-returning method, an await expression must be immediately returned.
If the body contains one await expression which does not match these rules, the diagnostic is not reported.
Additional context
The Analyzer should not report an await within a try or using block, since Tasks need to be awaited in these scenarios.