57

I'm unable to declare

interface IMyInterface
{
   async Task<myObject> MyMethod(Object myObj);
}

The compiler tells me:

  • The modifier async isn't valid for this item
  • The async modifier can only be used for methods that have a body

Is this something that should be implemented, or does the nature of async & await prohibit this from ever occurring?

halfbit
  • 54,462
  • 46
  • 195
  • 426

3 Answers3

65

Whether a method is implemented using async/await or not is an implementation detail. How the method should behave is a contract detail, which should be specified in the normal way.

Note that if you make the method return a Task or a Task<T>, it's more obvious that it's meant to be asynchronous, and will probably be hard to implement without being asynchronous.

From https://stackoverflow.com/a/6274601/43846

Community
  • 1
  • 1
stuartd
  • 62,136
  • 13
  • 120
  • 150
  • This could get ugly. Async method name usually should end with an `Async` suffix. Not able to enforce async implementation for a method defined in a interface (with `Async` in the name) means that we could have a non-async methods with Async suffix in their names. Or if we chose not to do so, we would have async methods without async suffix in their names. Is there a convention that people follow? – GiriB Mar 13 '19 at 11:10
  • Yes it is just convention, and like all conventions some people choose their own way. However as in the quote above, returning a `Task` / `Task` vs `void` / `T` does make it more obvious, and harder to implement incorrectly. – stuartd Mar 13 '19 at 11:43
19

Whether or not your implementation is async, has no relevance to your interface. In other words, the interface cannot specify that a given method must be implemented in an asynchronous way.

Just take async out of your interface and it will compile; however, there is no way to enforce asynchronous implementation just by specifying an interface.

Roy Dictus
  • 30,703
  • 5
  • 56
  • 69
6

If you have an interface with two implementations (one that is truly async and the other that is synchronous) this is what it would look like for each implementation - with both returning a Task<bool>.

public interface IUserManager
{
    Task<bool> IsUserInRole(string roleName);
}

public class UserManager1 : IUserManager
{
    public async Task<bool> IsUserInRole(string roleName)
    {
        return await _userManager.IsInRoleAsync(_profile.Id, roleName);
    }
}

public class UserManager2 : IUserManager
{
    public Task<bool> IsUserInRole(string roleName)
    {
        return Task.FromResult(Roles.IsUserInRole(roleName));
    }
}

If it is a void method you need to return Task.CompletedTask; from the non async method (I think .NET 4.5 and later)

See also : Return Task<bool> instantly

ANeves thinks SE is evil
  • 5,681
  • 3
  • 35
  • 60
Simon_Weaver
  • 120,240
  • 73
  • 577
  • 618