|<<>>|9 of 293 Show listMobile Mode

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);
}