Task<T> is a class and causes the unnecessary overhead of its allocation when the result is immediately available.

ValueTask<T> is a structure and has been introduced to prevent the allocation of a Task object in case the result of the async operation is already available at the time of awaiting.

So ValueTask<T> provides two benefits:

1. Performance increase

Here’s a Task<T> example:

async Task<int> TestTask(int d)
{
    await Task.Delay(d);
    return 10;
}

Here’s the analog ValueTask<T> example:

async ValueTask<int> TestValueTask(int d)
{
    await Task.Delay(d);
    return 10;
}

2. Increased implementation flexibility

Implementations of an async interface wishing to be synchronous would otherwise be forced to use either Task.Run or Task.FromResult (resulting in the performance penalty discussed above). Thus there’s some pressure against synchronous implementations.

But with ValueTask<T>, implementations are more free to choose between being synchronous or asynchronous without impacting callers.

For example, here’s an interface with an asynchronous method:

interface IFoo<T>
{
    ValueTask<T> BarAsync();
}

…and here’s how that method might be called:

IFoo<T> thing = getThing();
var x = await thing.BarAsync();

With ValueTask, the above code will work with either synchronous or asynchronous implementations: