3

这里提出的问题与这里的问题相同,旨在为它创建一个明确的解决方案。最准确的答案是 Stephen Toub 本人在这个问题上正是关于这个问题的。“推荐代码”如下:

public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
    if (valueTask.IsCompletedSuccessfully)
    {
        valueTask.GetResult();
        return default;
    }

    return new ValueTask(valueTask.AsTask());
}

这个答案不是最新的 - ValueTask 没有公开 GetResult() (只有 Result 属性) - 问题是:

  • 我们是否需要将 Result 从 ValueTask 中“拉”出来(以“释放”可能在此 ValueTask 下运行的 IValueTaskSource)?
  • 如是:
    • .GetAwaiter()上面缺少的电话吗?
    • 或者是一个假电话保证工作var fake = valueTask.Result;?总是?(我害怕死代码消除。)
  • 如果不是,那么像下面这样的直接实现是否足够(并且是最佳的)?
public static ValueTask AsNonGenericValueTask<T>( in this ValueTask<T> valueTask )
{
    return valueTask.IsCompletedSuccessfully ? default : new ValueTask( valueTask.AsTask() );
}
4

1 回答 1

3

该代码中缺少的是.GetAwaiter()

public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
    if (valueTask.IsCompletedSuccessfully)
    {
        valueTask.GetAwaiter().GetResult();
        return default;
    }

    return new ValueTask(valueTask.AsTask());
}

你部分正确,因为你不关心结果。但是您可能会关心如果您不查询结果会错过的抛出异常或取消。

或者你可以这样写:

public static async ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
    => await valueTask;
于 2020-04-16T21:06:11.823 回答