Solución:
si no encuentra resultados, ¿es mejor devolver una tarea vacía o nula?
Hay un par de cosas a considerar aquí:
Primero, deberías nunca devuelva un nulo Task
. En el async
mundo, un null
la tarea simplemente no tiene sentido. Task
representa la ejecución del método asincrónico, por lo que para que un método asincrónico devuelva un null
La tarea es como decirle al código de llamada “realmente no llamaste a este método” cuando, por supuesto, lo hizo.
Entonces, un Task
/Task<T>
devuelto de un método nunca, nunca debería ser null
. Sin embargo, aún tiene la opción de devolver un null
valor dentro de una tarea regular. Eso depende de ti.
con las tareas no estoy seguro de cuál es la mejor.
La tarea es solo un envoltorio. La lógica subyacente sigue siendo la misma. Piense en cómo se vería este método si fuera sincrónico; ¿Sería tu tipo de devolución? int
y volver 0
si no se encontró nada, o su tipo de devolución sería int?
y volver null
si no se encuentra nada? Después de hacer esa elección para un método síncrono, envuélvalo en Task<T>
para el método asincrónico.
Como nota final, debo decir:
- Nunca, siempre utilizar el
Task
constructor. - Evitar
Task<T>.Result
; usarawait
en lugar de. - No utilice
ContinueWith
; usarawait
en lugar de.
Su método se puede simplificar drásticamente:
public virtual async Task<int> GetJobRunIdAsync(int jobId)
{
var jobMonRequest = ...;
var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
if (jobMonResponse == null)
return 0;
if (jobMonResponse.jobrun.Length > 1)
throw new Exception("More than one job found, Wizards are abound.");
return jobMonResponse.jobrun.Single().id;
}
O, si desea devolver un valor (no tarea) de null
:
public virtual async Task<int?> GetJobRunIdAsync(int jobId)
{
var jobMonRequest = ...;
var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
if (jobMonResponse == null)
return null;
if (jobMonResponse.jobrun.Length > 1)
throw new Exception("More than one job found, Wizards are abound.");
return jobMonResponse.jobrun.Single().id;
}
Si realmente desea devolver un valor nulo del método asincrónico, puede usar Task.FromResult(null)
Por ejemplo:
public async Task<FileInfo> GetInfo()
{
return await Task.FromResult<FileInfo>(null);
}
La respuesta de Stephen Cleary lo explica a la perfección: nunca regreses null
, o provocarás excepciones de referencia nula pero quiero agregar algo:
- si su función devuelve un
Task
, devuelve una tarea completada, que se puede realizar devolviendoTask.CompletedTask
- si su función devuelve un
Task<T>
devolver una tarea completada deT
, que se puede hacer conTask.FromResult<TResult>(TResult)
Si devuelve nulo en lugar de una tarea completada, este código arrojará una excepción de referencia nula:
await FunctionThatShouldRetunrTaskButReturnsNull();
y es un poco difícil entender lo que está sucediendo incluso cuando lo ve en el depurador.
Entonces, nunca, nunca, devuelva un null
a partir de una no-async
función que devuelve un Task
.
Explicación:
- en un no
async
función, que devuelve unaTask
oTask<T>
, debe crear la tarea de forma explícita y existe el peligro de volvernull
en lugar de una tarea. - en un
async
función que devuelve unTask
oTask<T>
, simplemente devuelve o devuelve un valor, y el resultado de la función se convierte implícitamente en una tarea, por lo que no hay peligro de devolvernull
.