web-dev-qa-db-fra.com

L'utilisation du suffixe "Async" dans un nom de méthode dépend-elle de l'utilisation ou non du modificateur "async"?

Quelle est la convention de suffixe des noms de méthode avec "Async"?

Le suffixe "Async" doit-il être ajouté niquement à une méthode déclarée avec le modificateur async?

public async Task<bool> ConnectAsync()

Ou suffit-il que la méthode renvoie simplement Task<T> ou Task?

public Task<bool> ConnectAsync()
86
kasperhj

Je pense que la vérité est ambiguë même à partir de la documentation Microsoft:

Dans Visual Studio 2012 et .NET Framework 4.5, toute méthode attribuée avec le mot clé async (Async dans Visual Basic) est considérée comme une méthode asynchrone et les compilateurs C # et Visual Basic effectuent les transformations nécessaires pour implémenter la méthode de manière asynchrone à l'aide de TAP. Une méthode asynchrone doit renvoyer un Task ou un Task<TResult> objet.

http://msdn.Microsoft.com/en-us/library/hh873177 (v = vs.110) .aspx

Ce n'est pas déjà vrai. Toute méthode avec async est asynchrone, puis elle dit qu'elle doit renvoyer un Task ou Task<T> - ce qui ne convient pas aux méthodes en haut d'une pile d'appels, Button_Click par exemple, ou async void.

Bien sûr, vous devez considérer quel est le but de la convention?

Vous pourriez dire que la convention de suffixe Async est de communiquer à l'utilisateur de l'API que la méthode est attendue. Pour qu'une méthode soit attendue, elle doit renvoyer Task pour un vide, ou Task<T> pour une méthode de retour de valeur, ce qui signifie que seule cette dernière peut être suffixée avec Async.

Ou vous pourriez dire que la convention de suffixe Async est de communiquer que la méthode peut retourner immédiatement, abandonnant le thread actuel pour effectuer d'autres travaux et potentiellement provoquer des courses.

Cette citation de doc Microsoft dit:

Par convention, vous ajoutez "Async" aux noms des méthodes qui ont un modificateur Async ou async.

http://msdn.Microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention

Ce qui ne mentionne même pas que vos propres méthodes asynchrones renvoyant Task ont besoin du suffixe Async, ce qui, je pense, nous convenons tous.


La réponse à cette question pourrait donc être: les deux. Dans les deux cas, vous devez ajouter Async aux méthodes avec le mot clé async et qui renvoient Task ou Task<T>.


Je vais demander à Stephen Toub de clarifier la situation.

Mise à jour

Alors je l'ai fait. Et voici ce que notre brave homme a écrit:

Si une méthode publique renvoie une tâche et est de nature asynchrone (par opposition à une méthode qui est toujours connue pour s'exécuter de manière synchrone jusqu'à la fin mais qui renvoie toujours une tâche pour une raison quelconque), elle doit avoir un suffixe "Async". C’est la ligne directrice. Le but principal ici avec la dénomination est de rendre très évident pour un consommateur de la fonctionnalité que la méthode invoquée ne terminera probablement pas tout son travail de manière synchrone; bien sûr, cela aide également dans le cas où les fonctionnalités sont exposées avec des méthodes synchrones et asynchrones de sorte que vous avez besoin d'une différence de nom pour les distinguer. La façon dont la méthode réalise son implémentation asynchrone est sans importance pour la dénomination: si async/wait est utilisé pour obtenir l'aide du compilateur, ou si les types et méthodes de System.Threading.Tasks sont utilisés directement (par exemple TaskCompletionSource) n'a pas vraiment d'importance, car cela n'affecte pas la signature de la méthode en ce qui concerne un consommateur de la méthode.

Bien sûr, il existe toujours des exceptions à une directive. Le plus notable dans le cas de la dénomination serait les cas où la raison d’être d’un type entier est de fournir des fonctionnalités axées sur l’async, auquel cas avoir Async sur chaque méthode serait exagéré, par exemple les méthodes sur la tâche elle-même qui produisent d'autres tâches.

En ce qui concerne les méthodes asynchrones à retour de vide, il n'est pas souhaitable de les avoir dans la zone de surface publique, car l'appelant n'a aucun bon moyen de savoir quand le travail asynchrone est terminé. Si vous devez exposer publiquement une méthode asynchrone à retour de vide, vous souhaitez probablement avoir un nom qui indique que le travail asynchrone est en cours de lancement, et vous pouvez utiliser le suffixe "Async" ici si cela a du sens. Étant donné la rareté de ce cas, je dirais que c'est vraiment une décision au cas par cas.

J'espère que ça aide, Steve

Les indications succinctes de la phrase d’ouverture de Stephen sont suffisamment claires. Il exclut async void car il est inhabituel de vouloir créer une API publique avec une telle conception car la bonne façon d'implémenter un vide asynchrone est de retourner une instance de Task simple et de laisser le compilateur à sa magie. Cependant, si vous vouliez un public async void, puis l'ajout de Async est conseillé. Autre haut de pile async void les méthodes telles que les gestionnaires d'événements ne sont généralement pas publiques et n'ont pas d'importance/ne sont pas admissibles.

Pour moi, cela me dit que si je me pose des questions sur le suffixe Async sur un async void, Je devrais probablement en faire un async Task pour que les appelants puissent l'attendre, puis ajoutez Async.

103
Luke Puplett

Je construis beaucoup de services API et d'autres applications qui appellent d'autres systèmes où la plupart de mon code s'exécute de manière asynchrone.

Ma propre règle d'or que je suis est la suivante:

S'il existe des méthodes non asynchrones et asynchrones qui retournent la même chose, je suffixe celle async avec Async. Sinon non.

Exemples:

Une seule méthode:

public async Task<User> GetUser() { [...] }

Même méthode avec deux signatures:

public User GetUser() { [...] }

public async Task<User> GetUserAsync() { [...] }

Cela a du sens car ce sont les mêmes données qui sont retournées, mais la seule chose qui diffère est la manière de renvoyer les données , pas les données elles-mêmes.

Je pense également que ces conventions de dénomination existent en raison de la nécessité d'introduire des méthodes asynchrones et de maintenir la compatibilité descendante.

Je soutiens que le nouveau code ne devrait pas utiliser le suffixe Async. Il est tout aussi évident que le type de retour de String ou Int comme mentionné précédemment dans ce fil.

37
Jonas Stensved

Quelle est la convention pour le suffixe des noms de méthode avec "Async".

Le modèle asynchrone basé sur les tâches (TAP) dicte que les méthodes doivent toujours renvoyer un Task<T> (Ou Task) et être nommées avec un Async suffixe; ceci est distinct de l'utilisation de async. Task<bool> Connect() et asyncTask<bool> Connect() se compileront et fonctionneront très bien, mais vous avez gagné ne suivrez pas la convention de dénomination TAP.

La méthode doit-elle contenir le modificateur async, ou suffisamment pour qu'elle renvoie simplement Task?

Si le corps de la méthode (quel que soit le type ou le nom de retour) inclut await, vous devez utiliser async ; et le compilateur vous dira "L'opérateur 'wait' ne peut être utilisé que dans une méthode asynchrone. ...". Renvoyer Task<T> Ou Task n'est pas "suffisant" pour éviter d'utiliser async. Voir async (référence C #) pour plus de détails.

C'est à dire. lesquelles de ces signatures sont correctes:

Les deux asyncTask<bool> ConnectAsync() et Task<bool> ConnectAsync() suivent correctement les conventions TAP. Vous pourriez toujours utiliser le mot clé async, mais vous obtiendrez un avertissement du compilateur "Cette méthode asynchrone manque d'opérateurs" en attente "et s'exécutera de manière synchrone. ..." si le le corps n'utilise pas await.

23
Ðаn

ou suffit-il qu'il renvoie simplement la tâche?

Cette. Le mot clé async n'est pas le vrai problème ici. Si vous implémentez l'asynchronie sans utiliser le mot clé async, la méthode est toujours "Async", au sens général.

11
Servy

Depuis Task et Task<T> sont deux types attendus, ils représentent certains opération asynchrone. Ou du moins, ils devraient représenter.

Vous devez ajouter le suffixe Async à une méthode qui, dans certains cas (pas nécessairement tous), ne renvoie pas de valeur mais renvoie plutôt un wrapper autour d'une opération en cours. Ce wrapper est généralement un Task, mais sous Windows RT il peut être IAsyncInfo. Suivez votre intuition et rappelez-vous que si un utilisateur de votre code voit le Async, il saura que l'invocation de cette méthode est découplée du résultat de cette méthode et qu'ils doivent agir en conséquence.

Notez qu'il existe des méthodes telles que Task.Delay et Task.WhenAll qui renvoient Task et qui n'ont pas encore le suffixe Async.

Notez également qu'il existe async void méthodes qui représentent tirer et oublier méthode asynchrone et il vaut mieux être conscient que la méthode est construite de cette manière.

7
Toni Petrina

Je dirais qu'il devrait utiliser le suffixe Async s'il renvoie une tâche, que la méthode soit déclarée avec le modificateur async ou non.

La raison derrière cela est que le nom est déclaré dans l'interface. L'interface déclare le type de retour qui est un Task. Ensuite, il existe deux implémentations de cette interface, une implémentation l'implémente à l'aide du modificateur async, l'autre non.

public interface IFoo
{
    Task FooAsync();
}

public class FooA : IFoo
{
    public Task FooAsync() { /* ... */ }
}

public class FooB : IFoo
{
    public async Task FooAsync() { /* ... */ }
}
5
Fred

Dans Programmation asynchrone avec async et wait (C #) , Microsoft offre les conseils suivants:

Convention de dénomination

Par convention, vous ajoutez "Async" aux noms des méthodes qui ont un modificateur async .

Vous pouvez ignorer la convention selon laquelle un événement, une classe de base ou un contrat d'interface suggère un nom différent. Par exemple, vous ne devez pas renommer les gestionnaires d'événements courants, tels que Button1_Click.

Je trouve ces conseils incomplets et insatisfaisants. Est-ce à dire qu'en l'absence du modificateur async, cette méthode doit être nommée Connect au lieu de ConnectAsync?

public Task<bool> ConnectAsync()
{
    return ConnectAsyncInternal();
}

Je ne pense pas. Comme indiqué dans le réponse concise par @ Servy et plus réponse détaillée par @ Luke Puplett , je crois que il est approprié et en effet attendu que cette méthode devrait soit nommée ConnectAsync (car elle retourne un en attente). À l'appui de cela, @ John Skeet in cette réponse à une autre question ajoute Async au nom de la méthode indépendamment de la présence de async modificateur.

Enfin, sur autre question , considérez ce commentaire par @ Damien_The_Unbeliever :

async/await Sont implémentation détails de vos méthodes. Peu importe que votre méthode soit déclarée async Task Method() ou simplement Task Method(), en ce qui concerne vos appelants. (En fait, vous êtes libre de changer entre ces deux à un moment ultérieur sans que cela soit considéré comme un changement de rupture.)

J'en déduis que c'est la nature asynchrone de la méthode qui dicte comment elle doit être nommée. L'utilisateur de la méthode ne saura même pas si le modificateur async est utilisé dans son implémentation (sans le code source C # ou CIL).

4
DavidRR