According to the documentation a ValueTask<TResult>
...
Provides a value type that wraps a
Task<TResult>
and aTResult
, only one of which is used.
My question is about the state machine that the C# compiler generates when the async
keyword is encountered. Is it smart enough to generate a ValueTask<TResult>
that wraps a TResult
, when the result is available immediately, or one that wraps a Task<TResult>
, when the result comes after an await
? Here is an example:
static async ValueTask<DateTime> GetNowAsync(bool withDelay)
{
if (withDelay) await Task.Delay(1000);
return DateTime.Now;
}
static void Test()
{
var t1 = GetNowAsync(false);
var t2 = GetNowAsync(true);
}
Calling GetNowAsync(false)
should return a TResult
wrapper, because nothing is awaited, and calling GetNowAsync(true)
should return a Task<TResult>
wrapper, because a Task.Delay
is awaited before the result becomes available. I am worried about the possibility that the state machine always returns Task
wrappers, nullifying all the advantages of the ValueTask
type over the Task
(and keeping all the disadvantages). As far as I can tell the properties of the type ValueTask<TResult>
offer no indication about what it wraps internally. I pasted the code above to sharplab.io, but the output didn't help me to answer this question either.