Home > OS >  Two method overloads, async and sync lambda parameter, one implementation, no captured arguments. Is
Two method overloads, async and sync lambda parameter, one implementation, no captured arguments. Is

Time:11-04

I have a method LoopAsync that takes a lambda parameter, and invokes this lambda repeatedly a number of times with a delay. Both the method and the lambda are asynchronous:

static async Task LoopAsync(Func<int, Task> action,
    int start, int count, int delayMsec)
{
    for (int i = start; i < start   count; i  )
    {
        await Task.Delay(delayMsec).ConfigureAwait(false);
        await action(i).ConfigureAwait(false);
    }
}

Now I want to enhance the LoopAsync with an overload that takes a synchronous lambda parameter (an Action<int>). I want to avoid duplicating my code, so I am thinking to implement the overload using the existing implementation like this:

static Task LoopAsync(Action<int> action,
    int start, int count, int delayMsec)
{
    return LoopAsync(i =>
    {
        action(i); return Task.CompletedTask;
    }, start, count, delayMsec);
}

What I dislike with this approach is that it captures the action argument, resulting in an allocation of an object every time the LoopAsync is invoked. I want to prevent this capturing from happening. Is it possible?

Visual Studio screenshot

To summarize, I want to have two method overloads, the first with asynchronous lambda and the second with synchronous lambda, that are sharing the same implementation, without incurring the penalty of allocating closure objects on the heap. I am equally OK with the one overload being based on the other, or with both being based on the same private core implementation.

This question was inspired by a Visual Studio screenshot

According to my measurements, this optimization prevents the allocation of 88 bytes on the heap for each LoopAsync invocation (.NET 6, Release built).

  • Related