根据文档,
我的问题是关于当遇到
调用
ValueTask<TResult>
是一个值类型,它封装了一个Task<TResult>
和一个TResult
,只有其中之一被使用。我的问题是关于当遇到
async
关键字时,C#编译器生成的状态机是否足够智能,以便在结果立即可用时生成封装TResult
的ValueTask<TResult>
,或者在结果在经过await
后才可用时生成封装Task<TResult>
的ValueTask<TResult>
。以下是一个示例: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);
}
调用
GetNowAsync(false)
应返回TResult
包装器,因为没有等待任何内容,而调用GetNowAsync(true)
应返回Task<TResult>
包装器,因为Task.Delay
在结果可用之前被等待。 我担心状态机始终返回Task
包装器,这将使ValueTask
类型的所有优势无效(并保留所有劣势)。就我所知,ValueTask<TResult>
类型的属性没有提供关于其内部包装内容的指示。 我在sharplab.io上复制了上面的代码,但输出也没有帮助我回答这个问题。
ValueTask
,则在状态机生成后它将继续返回它。它没有足够的空间来变得“聪明”。 - Dmytro MukalovValueTask
中包含了什么。 - Theodor ZouliasTask
类型不会从Task.Delay
中泄漏,始终会返回ValueTask<DateTime>
。每个异步方法都由自己的状态机表示,该状态机公开特定的等待器类型,将由更高级别的消费者使用,而Task.Delay
公开Task
对状态机周围的GetNowAsync
没有影响 - 它只知道如何获取Task
等待器以及如何使用等待器异步地获取结果。 - Dmytro MukalovValueTask
?如果不熟悉,这里有一个很好的介绍:了解 ValueTask 的原因、内容和时间。由Task.Delay
返回的类型对我的问题没有影响。我询问的是在调用async
方法时可能发生的await
影响(或不影响)。 - Theodor ZouliasValueTask
)公开。 - Dmytro MukalovValueTask
值的非公共部分有关,具体来说是它们内部包装了什么,因为这会影响性能。我的基准测试显示,包装TResult
的ValueTask
创建和等待的速度比包装Task<TResult>
的ValueTask
快3倍。顺便说一句,这给了我一个关于如何回答我的问题的想法! - Theodor Zoulias