Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a method that can handle Task and ValueTask?

Tags:

c#

c#-7.0

Imagine you want to write a method similar to the following one. It wraps a function returning a ValueTask<T> with trivial performance monitoring 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 could simply duplicate the code and change just the parameter's type.

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

The implementation would be absolutely identical. I am asking myself if it is possible to avoid this kind of code duplication when having to deal with ValueTask and Task. Up to now, I could not come up with a good solution. Any ideas?

like image 961
Rainer Avatar asked May 10 '17 10:05

Rainer


1 Answers

According to official documentation: Generalized async return types

The ValueTask struct has a constructor with a Task parameter so that you can construct a ValueTask from the return value of any existing async method:

That means you can write an overload that will wrap the body and call only one method that will do the work

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);
}
like image 61
Sir Rufo Avatar answered Nov 13 '22 04:11

Sir Rufo