2012-08-24 28 views
6

Esperemos que esto no sea una repetición, pero hay más de 5000 preguntas aquí con "¡no todas las rutas de códigos devuelven un valor"!¿Por qué este código async/await genera "... no todas las rutas de código devuelven un valor"?

En pocas palabras, ¿por qué este método con una aplicación no genérico compilar bien:

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(); 
    } 

mientras que este intento de hacer que el método genérico genera una Return state missing/... not all code paths return a value de advertencia/error ?:

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(); 
    } 
+0

@LB \ * "* * debe retorno' Task' y ... –

Respuesta

8

El tipo no genérico Task es en cierto modo equivalente a un método void awaitable. Al igual que un método de anulación, no puede devolver nada de un método que tenga un tipo de devolución de Task, por lo que el primer ejemplo se compila. El segundo ejemplo, sin embargo, espera un valor de retorno del tipo genérico y no está proporcionando uno en la ruta donde espera otra llamada.

Citando del MSDN reference en la palabra clave async, específicamente sobre los tipos de devolución.

Usa la Tarea si no se devuelve ningún valor significativo cuando el método está completado. Es decir, una llamada al método devuelve una tarea, pero cuando se completa la tarea , cualquier expresión en espera que esté esperando la tarea se evalúa como vacía.

+2

Mi entendimiento es que el valor de la expresión Await se aplica * * para el valor de retorno , por lo que no es equivalente a devolver Void, sin embargo, espera en sí mismo es 'System.Void'. –

+1

Es cierto que el método devuelve implícitamente una' Tarea' que luego puede esperar. Es equivalente a vacío en el sentido de que no está permitido devuelva un valor del método usted mismo y no se le puede asignar nada como resultado de esperar ese método. En el caso de 'Tarea ', la 'T' que devuelve se podrá asignar desde una espera (por ej.' var value = await SomeCall(); '). –

+0

Gracias, gran explicación. Tiene sentido ahora, pero inicialmente la capa de la acción del constructo me estaba arrojando. – HolySamosa

7

En el segundo ejemplo que le diste, no devolvió nada. (Vea la respuesta de Chris Hannon para saber por qué).

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(); 
} 

Además de lo que dijo @ChrisHannon, desde el await documentation.

... si await se aplica al resultado de una llamada a un método que devuelve un Task<TResult>, entonces el tipo de la expresión es lo esperan TResult. Si se aplica await al resultado de una llamada a un método que arroja un Task, entonces el tipo de expresión de espera es void. ...

+0

Gracias, David. Aprecio el ejemplo. – HolySamosa

Cuestiones relacionadas