Does the use of the "Async" suffix in a method name depend on whether the 'async' modifier is used?

55,914

Solution 1

I think the truth is ambiguous even from Microsoft documentation:

In Visual Studio 2012 and the .NET Framework 4.5, any method that is attributed with the async keyword (Async in Visual Basic) is considered an asynchronous method, and the C# and Visual Basic compilers perform the necessary transformations to implement the method asynchronously by using TAP. An asynchronous method should return either a Task or a Task<TResult> object.

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

That's not right already. Any method with async is asynchronous and then its saying it should return either a Task or Task<T> - which isn't right for methods at the top of a call stack, Button_Click for example, or async void.

Of course, you have to consider what is the point of the convention?

You could say that the Async suffix convention is to communicate to the API user that the method is awaitable. For a method to be awaitable, it must return Task for a void, or Task<T> for a value-returning method, which means only the latter can be suffixed with Async.

Or you might say that the Async suffix convention is to communicate that the method can return immediately, relinquishing the current thread to perform other work and potentially causing races.

This Microsoft doc quote says:

By convention, you append "Async" to the names of methods that have an Async or async modifier.

Content now only available via the Wayback Machine

Which doesn't even mention that your own asynchronous methods returning Task need the Async suffix, which I think we all agree they do.


So the answer to this question could be: both. In both cases, you need to append Async to methods with async keyword and that return Task or Task<T>.


I'm going to ask Stephen Toub to clarify the situation.

Update

So I did. And here's what our good man wrote:

If a public method is Task-returning and is asynchronous in nature (as opposed to a method that is known to always execute synchronously to completion but still returns a Task for some reason), it should have an “Async” suffix. That’s the guideline. The primary goal here with the naming is to make it very obvious to a consumer of the functionality that the method being invoked will likely not complete all of its work synchronously; it of course also helps with the case where functionality is exposed with both synchronous and asynchronous methods such that you need a name difference to distinguish them. How the method achieves its asynchronous implementation is immaterial to the naming: whether async/await is used to garner the compiler’s help, or whether types and methods from System.Threading.Tasks are used directly (e.g. TaskCompletionSource) doesn’t really matter, as that doesn’t affect the method’s signature as far as a consumer of the method is concerned.

Of course, there are always exceptions to a guideline. The most notable one in the case of naming would be cases where an entire type’s raison d’etre is to provide async-focused functionality, in which case having Async on every method would be overkill, e.g. the methods on Task itself that produce other Tasks.

As for void-returning asynchronous methods, it’s not desirable to have those in public surface area, since the caller has no good way of knowing when the asynchronous work has completed. If you must expose a void-returning asynchronous method publicly, though, you likely do want to have a name that conveys that asynchronous work is being initiated, and you could use the “Async” suffix here if it made sense. Given how rare this case should be, I’d argue it’s really a case-by-case kind of decision.

I hope that helps, Steve

The succinct guidance from Stephen’s opening sentence is clear enough. It excludes async void because it is unusual to want to create a public API with such a design since the correct way to implement an asynchronous void is to return a plain Task instance and let the compiler to its magic. However, if you did want a public async void, then appending Async is advised. Other top-of-stack async void methods such as event handlers are usually not public and don’t matter/qualify.

For me, it tells me that if I find myself wondering about suffixing Async on an async void, I probably should turn it into an async Task so that callers can await it, then append Async.

Solution 2

I build a lot API-services and other applications that call others systems where most of my code is running asynchronous.

My own rule of thumb I'm following is:

If there is both non-async and async method that return the same thing I suffix the async one with Async. Otherwise not.

Examples:

Only one method:

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

Same method with two signatures:

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

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

This makes sense since it's the same data that is returned but the only thing that differs is the way of returning data, not the data itself.

I also think this naming conventions exists due to the need to introduce async methods and still maintain backwards compatibility.

I argue that new code shouldn't use the Async suffix. It is just as obvious as return type of String, or Int as mentioned before in this thread.

Solution 3

What is the convention for suffixing method names with "Async".

The Task-based Asynchronous Pattern (TAP) dictates that methods should always return a Task<T> (or Task) and be named with an Async suffix; this is separate from the use of async. Both Task<bool> Connect() and asyncTask<bool> Connect() will compile and run just fine, but you won't be following the TAP naming convention.

Should the method contain the async modifier, or it enough that it just returns Task?

If the body of the method (regardless of the return type or name) includes await, you must use async; and the compiler will tell you "The 'await' operator can only be used within an async method. ...". Returning Task<T> or Task is not "enough" to avoid using async. See async (C# Reference) for details.

I.e. which of these signatures are correct:

Both asyncTask<bool> ConnectAsync() and Task<bool> ConnectAsync() properly follow the TAP conventions. You could always use the async keyword, but you'll get a compiler warning "This async method lacks 'await' operators and will run synchronously. ..." if the body doesn't use await.

Solution 4

or it enough that it just returns Task?

That. The async keyword isn't the real issue here. If you implement the asynchrony without using the async keyword the method is still "Async", in the general sense.

Solution 5

I would argue that it should use the Async-suffix if it returns a Task regardless if the method is declared with the async modifier or not.

The reason behind it being that the name is declared in the interface. The interface declares the return type which is a Task. Then there are two implementations of that interface, one implementation implements it using the async modifier, the other does not.

public interface IFoo
{
    Task FooAsync();
}

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

public class FooB : IFoo
{
    public async Task FooAsync() { /* ... */ }
}
Share:
55,914
kasperhj
Author by

kasperhj

Updated on April 19, 2021

Comments

  • kasperhj
    kasperhj about 3 years

    What is the convention for suffixing method names with "Async"?

    Should the "Async" suffix be appended only to a method that is declared with the async modifier?

    public async Task<bool> ConnectAsync()
    

    Or is it enough that the method just returns Task<T> or Task?

    public Task<bool> ConnectAsync()
    
    • James Manning
      James Manning about 11 years
      For the naming part, the TAP doc says: Asynchronous methods in TAP include the Async suffix after the operation name; for example, GetAsync for a get operation. If you're adding a TAP method to a class that already contains that method name with the Async suffix, use the suffix TaskAsync instead. For example, if the class already has a GetAsync method, use the name GetTaskAsync.
    • kasperhj
      kasperhj about 11 years
      Yes, I know that "Async" should be appended to the method name, but that is really not the question.
    • James Manning
      James Manning about 11 years
      ok, I guess I was confused by the question title of "Naming convention for async methods"
    • Luke Puplett
      Luke Puplett almost 10 years
      This is a poorly constructed question. People bickering, equivocal answers.
    • kasperhj
      kasperhj almost 10 years
      Why do you think it's poorly constructed?
    • Luke Puplett
      Luke Puplett almost 10 years
      Because many people have misunderstood it and are arguing as to the actual thing being asked, wondering whether its a two-part question etc. The proof that its confusing is that people are confused.
    • BenjaminPaul
      BenjaminPaul about 9 years
      Poorly worded question.
    • kasperhj
      kasperhj about 9 years
      @BenjaminPaul Why do you think so? I can't figure out why people misunderstand this question.
    • DavidRR
      DavidRR almost 8 years
      After reading your original question and subsequent edits as well as the answers, in editing your question I believe I've clarified your intent. If this is not the case, please let me know. Of course, you can edit further or even roll back my changes. Regardless, if the result of my changes is not the question that you asked, it is the question whose answer I am seeking. :-)
    • kasperhj
      kasperhj almost 8 years
      @DavidRR To this day I still don't understand the amount of confusion that this question apparently has caused. If your edits bring some order in the confusion such that it has helped you and possibly can help others, then I welcome your edits for you have achieved something that I could not in the original formulation. The question is now so old now that I can hardly recall my mindset when I asked it here and so the original intent is less important. Luke's answer reflect that not all were confused. I found it immensely helpful.
    • kasperhj
      kasperhj over 7 years
      I suddenly remember what I was thinking when asking the question. The fundamental problem is intent. I can write a method returning a Task and add the "Async" suffix, but the method might or might not be blocking. Adding the async keyword could more clearly communicate the intent, i.e. suggesting more strongly that a method is indeed asynchronous.
    • Gurpreet
      Gurpreet over 3 years
      I also believe that the method names should focus on the what they are doing and not how they are are doing it. Soon as method returns as task, it is understood that execution will happen asynchronously. I cant think of a reason a method will return a task but not do any asynchronous work. Only thing the Async suffix helps with is reducing the probability of programmer to forget awaiting when it should be awaited, but that is easily mitigated with help full warning form visual studio or similar IDE
  • Servy
    Servy about 11 years
    He's referring to whether or not you append "Async" to the method name, not whether you use the async keyword.
  • Corak
    Corak about 11 years
    @Servy wether or not using the keyword async is the second part of the question.
  • Servy
    Servy about 11 years
    @Corak The OP isn't asking if he should be using the async keyword on his methods. He clearly already knows when he needs to. He's asking if a method that doesn't have the async keyword, but returns a task, should use append Async to the method name. This answer, while not wrong, is addressing an entirely different question than what the OP is asking, which is not helpful.
  • Corak
    Corak about 11 years
    @Servy It is a two part question. The first part, as you said is whether or not to append "Async" to the method name. The second part is whether or not to use the async modifier. See also OPs examples, public async Task<bool> ConnectAsync() (with async modifier) vs public Task<bool> ConnectAsync() (without async modifier). The method name itself has the suffix "Async" in both cases.
  • kasperhj
    kasperhj about 11 years
    It is not a two part question. The question is, should "Async" be appended to methods names of methods that return Task or methods that have async Task.
  • kasperhj
    kasperhj about 11 years
    @Dan It is now modified to make it clear that it is not a two part question. I don't think you can make much sense from the "vs." snippets without looking at the title and the accompanying text.
  • Piotr Kula
    Piotr Kula almost 7 years
    Well its a shame we don't have compile time checks for method calls.. oh wait. If I name the Method Get or GetAsync and don't use await from the calling side, the compile will fail to build. So this convention is SILLY and really going against many Microsoft Style guidelines, like avoiding things like PersonString or PriceDecimal so why use GetAsync - API consumers of async API's need not worry about this as the request always returns after all tasks complete anyway. Its silly and really annoying me. But its just another convention that nobody really knows why its there.
  • m.rufca
    m.rufca almost 7 years
    For code conventions propose.. Should signature method show implementation details?
  • djk
    djk over 6 years
    @ppumkin: As Stephen pointed out, a method can easily be asynchronous in nature without using async/await, thus the caller doesn't have any indication other than the name whether or not the functionality runs asynchronous.
  • Bartosz
    Bartosz almost 6 years
    I agree, especially that usually you need to go 'async all the way', in which case the suffix is redundant - what is the point of appending it to 90% of the code;)
  • Dustin Cleveland
    Dustin Cleveland almost 6 years
    @ppumkin: Failing to await an async method, by default, results in a compile-time warning; not a build error.
  • Marco
    Marco almost 6 years
    I find this convention silly. There are three automatic indications that a method is async: 1. The return type is Task. 2. Code completion presents an awaitable hint 3. the IDE will warn you by underlining in green and presenting a compiler warning. So I totally agree with @ppumkin. The Async-suffix is as silly as if you wrote a property like so: public Lazy<Customer> CustomerLazy. Who would do this!??
  • Marco
    Marco almost 6 years
    BTW: I agree with @Hannobo, there are exceptions where a consumer of your API may not know if your method runs async. But I would consider such a method "dirty", because the proper way to do it is to always return an awaitable task if your method can run async. THIS should be the convention, and not some meanlingless Async-suffix.
  • Marco
    Marco almost 6 years
    this is the best solution. Without noticing it, I've been doing the same way in my APIs.
  • Luke Puplett
    Luke Puplett almost 6 years
    @Marco I raised this idea on GitHub, thought it was the best place, but don't have the engagement with it I thought I'd get: github.com/dotnet/core/issues/1464
  • Marco
    Marco almost 6 years
    @LukePuplett Thanks for pointing this out. I just added my support there.
  • Christian Findlay
    Christian Findlay over 5 years
    This is an excellent answer. It might be tempting to base whether or not to suffix the method on whether or not the call is naturally async - i.e. without CPU work. However, this is irrelevant to the caller. The Async suffix should mean that calling a method will block work like UI work.
  • Mariusz Jamro
    Mariusz Jamro over 5 years
    This is way better than suffixing wiht "Async" all methods of async application
  • David
    David about 5 years
    The problem with this technique is that if you create a non-async version later, you can't use your otherwise preferred "GetUser()" name.
  • Skrymsli
    Skrymsli about 5 years
    This is the pragmatic way to go. Appending Async to every method that has the async modifier is just Hungarian Notation 2019. @David if you end up adding a non-async version later, then rename the methods and follow the naming convention or just don't do that.
  • xhafan
    xhafan about 5 years
    @DustinCleveland In Visual Studio 2017, you can treat the warning as an error by adding <PropertyGroup> <WarningsAsErrors>NU1605;CS4014</WarningsAsErrors> </PropertyGroup> into the csproj file (NU1605 was already there as a default; CS4014 is the await missing warning.
  • Rick O'Shea
    Rick O'Shea almost 5 years
    As many have pointed out this stinks of the Hungarian notation Microsoft pushed for a decade with virtually no benefit and plenty of downside. The lemmings instantly agreed it was a bad idea after Microsoft finally capitulated. Do want a clue as to why this is SILLY? Look at that long-winded blather of an answer for the world's simplest question. Apparently 'concision" isn't a valued quality.
  • Skrymsli
    Skrymsli almost 5 years
    By default, you get no warnings when you inject an interface and call an a method from that interface that returns a task and ought to be awaited in some form. The Async suffix is the only obvious indication that the method should be awaited.
  • afruzan
    afruzan over 4 years
    it is different from Microsoft suggestion. best solution is adding Async suffix to methods that return Task or Task<> OR have async keyword.
  • Al Kepp
    Al Kepp over 4 years
    This is so true. We always use interfaces, everywhere, and interfaces cannot be declared async. So the official guides on using Async suffix seem completely nonsense to me. I think that async keyword is just an implementation detail, part of method's internals, and should not influence its name or whatever external.
  • Gabriel Luci
    Gabriel Luci over 4 years
    @Skrymsli "returns a task" - That's the obvious indication that the method should be awaited.
  • Luke Puplett
    Luke Puplett over 4 years
    @GabrielLuci In practice this is probably true, but its worth remembering that awaitables work a little like enumerators, so a method does not have to return a Task. devblogs.microsoft.com/pfxteam/await-anything
  • Gabriel Luci
    Gabriel Luci over 4 years
    @LukePuplett True, although the compiler will still give you the same warnings about not awaiting those, like like Task.
  • Luke Puplett
    Luke Puplett over 4 years
    @GabrielLuci Sorry I was assuming what Skrymsli says was correct, forcing us to do our own checks, but actually we do get warnings on injected interfaces. Maybe we didn't used to.