Eu tenho uma interface com algumas funções assíncronas.
Métodos retornando Task, eu acredito. asyncé um detalhe de implementação, portanto, não pode ser aplicado a métodos de interface.
Algumas das classes que implementam a interface não têm nada a esperar, e algumas podem apenas lançar.
Nesses casos, você pode tirar vantagem do fato de que asyncé um detalhe de implementação.
Se você não tiver nada para fazer await, pode simplesmente retornar Task.FromResult:
public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
No caso de arremesso NotImplementedException, o procedimento é um pouco mais prolixo:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
Se você tiver muitos métodos de lançamento NotImplementedException(o que por si só pode indicar que alguma refatoração no nível de design seria boa), você poderia resumir o prolixo em uma classe auxiliar:
public static class TaskConstants<TResult>
{
static TaskConstants()
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetException(new NotImplementedException());
NotImplemented = tcs.Task;
}
public static Task<TResult> NotImplemented { get; private set; }
}
public Task<int> Fail() // note: no "async"
{
return TaskConstants<int>.NotImplemented;
}
A classe auxiliar também reduz o lixo que o GC teria que coletar, uma vez que cada método com o mesmo tipo de retorno pode compartilhar seus objetos Taske NotImplementedException.
Tenho vários outros exemplos de tipo de "constante de tarefa" em minha biblioteca AsyncEx .