How do I write a method that can handle Task and ValueTask?

Imagine that you want to write a method similar to the following. It wraps a function that returns ValueTask<T>

trivial performance control code:

static async Task Measure<T>(Func<ValueTask<T>> body)
{
    Console.WriteLine($"Starting perf test");
    var sw = Stopwatch.StartNew();
    await body();
    sw.Stop();
    Console.WriteLine(sw.Elapsed);
}

      

My question is, is there a way to write this function once so that it can receive Func<ValueTask<T>>

and Func<Task<T>>

?

Of course, you can just duplicate the code and only change the type of the parameter.

static async Task Measure<T>(Func<Task<T>> body) { ... }

      

The implementation will be exactly the same. I ask myself if this kind of code duplication can be avoided when dealing with ValueTask

and Task

. Until now, I couldn't find a good solution. Any ideas?

+3


source to share


1 answer


According to the official documentation: Generic async return types

The struct ValueTask

has a parameterized constructor Task

, so you can build ValueTask

from the return value of any existing async method:



This means that you can write an overload that will wrap body

and call only one method that will do the job

static Task Measure<T>(Func<Task<T>> body)
{
    var wrapped = () => new ValueTask<T>( body() );
    return Measure( wrapped );
}

static async Task Measure<T>(Func<ValueTask<T>> body)
{
    Console.WriteLine($"Starting perf test");
    var sw = Stopwatch.StartNew();
    await body();
    sw.Stop();
    Console.WriteLine(sw.Elapsed);
}

      

+3


source







All Articles