Почему этот код async / await генерирует "...не все пути кода возвращают значение"?

надеюсь, это не повторение, но здесь есть 5000+ вопросов с "не все пути кода возвращают значение"!

довольно просто, почему этот метод с неродовой реализацией компилируется просто отлично:

    public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
    {
        if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
            await task;
        else
            throw new TimeoutException();
    }

в то время как эта попытка сделать метод generic генерирует Return state missing / ...not all code paths return a value предупреждения / ошибки?:

    public static async Task<T> TimeoutAfter<T>(this Task<T> task, int millisecondsTimeout)
    {
        if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
            await task;
        else
            throw new TimeoutException();
    }

2 ответов


необщего Task type несколько эквивалентен ожидаемому методу void. Так же, как метод void, вы не могу вернуть что-либо из метода, который имеет тип возврата Task, поэтому первый пример компилируется. Второй пример, однако, ожидает возвращаемое значение универсального типа, и вы не предоставляете его в пути, где вы ждете другого вызова.

слово MSDN reference на async ключевое слово, а конкретно о типах возврата.

вы используете Task, если при методе не возвращается значимое значение завершенный. То есть вызов метода возвращает задачу, но когда Задача завершена, любое ожидающее выражение, которое ожидает задачу возвращает void.


во втором примере, который вы дали, вы ничего не вернули. (См. ответ Криса Хэннона почему).

public static async Task<T> TimeoutAfter<T>(this Task<T> task, int millisecondsTimeout) {
    if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
        return await task; // return the Task of T
    else
        throw new TimeoutException();
}

в дополнение к тому, что сказал @ChrisHannon, из ждем документация.

... если await применяется к результату вызова метода, который возвращает Task<TResult>, тогда типом выражения await является TResult. Если await применяется к результату вызова метода, который возвращает Task, затем тип ожидания выражение void. ...