J'ai une interface avec des fonctions asynchrones.
Les méthodes reviennent Task
, je crois. async
est un détail d'implémentation, il ne peut donc pas être appliqué aux méthodes d'interface.
Certaines des classes qui implémentent l'interface n'ont rien à attendre, et certaines pourraient simplement lancer.
Dans ces cas, vous pouvez profiter du fait qu'il async
s'agit d'un détail d'implémentation.
Si vous avez rien à await
, vous pouvez simplement revenir Task.FromResult
:
public Task<int> Success() // note: no "async"
{
... // non-awaiting code
int result = ...;
return Task.FromResult(result);
}
Dans le cas du lancer NotImplementedException
, la procédure est un peu plus verbeuse:
public Task<int> Fail() // note: no "async"
{
var tcs = new TaskCompletionSource<int>();
tcs.SetException(new NotImplementedException());
return tcs.Task;
}
Si vous avez beaucoup de méthodes à lancer NotImplementedException
(ce qui en soi peut indiquer qu'une refactorisation au niveau de la conception serait bonne), alors vous pouvez résumer la verbosité dans une classe d'assistance:
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;
}
La classe d'assistance réduit également les déchets que le GC devrait autrement collecter, car chaque méthode avec le même type de retour peut partager ses objets Task
et NotImplementedException
.
J'ai plusieurs autres exemples de type "constante de tâche" dans ma bibliothèque AsyncEx .