-1

First I used async delegates in this way:

public async Task TestWithAsyncDelegate()
{
    await MethodWithAsyncDelegate(async (counter) => await AsyncLoad(counter));
}

But after some time, I found that if the used delegate contains only one call, it can be simplified to:

public async Task TestWithoutAsyncDelegate()
{
    await MethodWithAsyncDelegate(counter => AsyncLoad(counter));
}

Is this code equivalent? In this case, embedding lambda in another delegate, it is redundant in my opinion. So I am using it.

Does somebody have an explanation why?

This approach cannot be used if called lambda has to await in its body:

public async Task TestWithMultipleCalls()
{
    await MethodWithAsyncDelegate(async (counter) =>
    {
        await Task.Delay(10);
        await AsyncLoad(counter);
    });
}

Complete code follows:

public class AsyncDelegateTests
{

    [Fact]
    public async Task TestWithAsyncDelegate()
    {
        await MethodWithAsyncDelegate(async (counter) => await AsyncLoad(counter));
    }

    [Fact]
    public async Task TestWithoutAsyncDelegate()
    {
        await MethodWithAsyncDelegate(counter => AsyncLoad(counter));
    }

    [Fact]
    public async Task TestWithMultipleCalls()
    {
        await MethodWithAsyncDelegate(async (counter) =>
        {
            await Task.Delay(10);
            await AsyncLoad(counter);
        });
    }

    /// <summary>
    /// simulate async work
    /// </summary>
    private async Task AsyncLoad(int counter)
    {
        await Task.Delay(10);
    }

    private async Task MethodWithAsyncDelegate(Func<int, Task> asyncDelegate)
    {
        for (int i = 0; i < 10 ; i++)
        {
            await asyncDelegate(i);
        }
    }

}
Servy
  • 202,030
  • 26
  • 332
  • 449
Karel Kral
  • 5,297
  • 6
  • 40
  • 50
  • That method simplifies all the way down to: `public Task TestWithoutAsyncDelegate() => MethodWithAsyncDelegate(AsyncLoad);` when you just apply the same transformation everywhere and also remove methods that do nothing but call another method with the same signature and behavior. – Servy Jan 17 '19 at 16:21
  • 1
    The problem (based on [this][1] question and [Stephen Cleary's blog post][2]) can be described as **Should I await on return keyword?**. As Stephen Cleary writes in his blog post: > Do consider eliding `await` when the method is just a passthrough or overload. So the next code is correct answer in this case: public async Task TestWithoutAsyncDelegate() { await MethodWithAsyncDelegate(AsyncLoad); } [1]: https://stackoverflow.com/q/19098143/245460 [2]: http://blog.stephencleary.com/2016/12/eliding-async-await.html – Karel Kral Jan 18 '19 at 02:26

1 Answers1

0

In the first example c# will wrap your async,await in another task because of the async method or lambda which has a very slight impact in performance

in the other example though it returns the task as is and it's up to the one that needs to await or consume the value to await it.

if you are not going to use the value in that lambda it's best to just return the task to prevent wrapping your task in another task

Servy
  • 202,030
  • 26
  • 332
  • 449
Abdo
  • 322
  • 6
  • 15