Преобразовать ValueTask <T>в не универсальный c ValueTask - PullRequest
1 голос
/ 16 апреля 2020

Вопрос, заданный здесь, такой же, как и здесь , и нацелен на создание окончательного решения. Самый точный ответ - сам Стивен Туб в этой проблеме , которая именно об этом вопросе. «Рекомендованный код» следующий:

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

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

Этот ответ не актуален - ValueTask не предоставляет GetResult () (только свойство Result) - и вопрос :

  • Нужно ли нам «извлекать» Результат из ValueTask (чтобы «освободить» IValueTaskSource, который может работать под этим ValueTask)?
  • Если да:
    • - это тот вызов .GetAwaiter(), который отсутствует выше?
    • ИЛИ это фальшивый вызов собственности гарантированно сработает var fake = valueTask.Result;? Всегда? (Я боюсь устранения мертвого кода.)
  • Если нет, достаточно ли (и оптимально) прямой реализации, подобной следующей?
public static ValueTask AsNonGenericValueTask<T>( in this ValueTask<T> valueTask )
{
    return valueTask.IsCompletedSuccessfully ? default : new ValueTask( valueTask.AsTask() );
}

1 Ответ

1 голос
/ 17 апреля 2020

В этом коде отсутствует .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;
...