Don’t return await
unless you have to
Published by marco on
I finally got around to verifying that the defining dependent async methods like the following one is wasteful.
public async Task<bool> N()
{
return await M();
}
A less-contrived example looks like this:
using System.Threading.Tasks;
public class C {
public Task<bool> M()
{
return Task.FromResult(false);
}
public async Task<bool> N()
{
return await M();
}
public async void RunIt()
{
var result = await N();
}
}
This yields something like the following lowered C# code in SharpLab.IO. Note that there are two state machines.
public Task<bool> M()
{
return Task.FromResult(false);
}
[AsyncStateMachine(typeof(<N>d__1))]
[DebuggerStepThrough]
public Task<bool> N()
{
<N>d__1 stateMachine = new <N>d__1();
stateMachine.<>t__builder = AsyncTaskMethodBuilder<bool>.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<RunIt>d__2))]
[DebuggerStepThrough]
public void RunIt()
{
<RunIt>d__2 stateMachine = new <RunIt>d__2();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
}
If you write the equivalent code without the await
in the N
method:
using System.Threading.Tasks;
public class C {
public Task<bool> M()
{
return Task.FromResult(false);
}
public Task<bool> N()
{
return M();
}
public async void RunIt()
{
var result = await N();
}
}
…then you get the following lowered C#. Note that now there is only one state machine.
public Task<bool> M()
{
return Task.FromResult(false);
}
public Task<bool> N()
{
return M();
}
[AsyncStateMachine(typeof(<RunIt>d__2))]
[DebuggerStepThrough]
public void RunIt()
{
<RunIt>d__2 stateMachine = new <RunIt>d__2();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
}