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()
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 unTask
ou unTask<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
.
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.
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 async
Task<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 async
Task<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
.
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.
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.
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() { /* ... */ }
}
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éeasync Task Method()
ou simplementTask 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).