Unable to declare Interface " async Task<myObject> MyMethod(Object myObj); " [duplicate] - c#

This question already has answers here:
Error: "Cannot use 'async' on methods without bodies". How to force async child overrides?
(2 answers)
Closed 1 year ago.
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?

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/4384

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.

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

The async modifier is an 'implementation detail', it affects how a method can do stuff asynchronously, not if it does so.
So async has no business being inside an interface.
interface IService { Task DoSomethingAsync(); }
class A : IService { public async Task DoSomethingAsync() { ... } }
class B : IService { public Task DoSomethingAsync() { ... } }
Classes A and B are both perfectly valid. Both methods are awaitable. A consumer of the interface doesn't know or care if they use async.
B.DoSomethingAsync() can be and probably will be asynchronous.

Related

C# Generic method calling two different services

I have the following method, which is to add product using the injected service! It is called inside a static calls hence it is static!
public static async Task AddNewProducts(Guid shopId)
{
var productAService = IoC.Services.GetService<IProductAService>();
var added = await productAService.AddProduct(shopId);
}
It works fine but I need to make it generic so that I can use different services with it.
Something like this!
public static async Task AddNewProducts<T>(Guid shopId)
where T : IProductAService, IProductBService
{
var productService = IoC.Services.GetService<T>();
var added = await productService.AddProduct(shopId);
}
However the second methods complains that the AddProduct method is ambiguous, not sure how I can make sure it is calling the right method from the related service!
Your 2 services need a common interface
public interface IProductService
{
void AddProduct(Guid shopId);
}
public interface IProductAService : IProductService
{
//specifics to service A
}
public interface IProductBService : IProductService
{
//specifics to service B
}
Then your static, generic method just constrains to the shared interface
public static async Task AddNewProducts<TProductService>(Guid shopId)
where TProductService : IProductService
{
var productService = IoC.Services.GetService<TProductService>();
await productService.AddProduct(shopId);
}
This gets slippery very quickly. You hinted that AddProduct is not a void, but returns a particular object. That's fine, you can make IProductService itself generic
public interface IProductService<TProduct>
{
TProduct AddProduct(Guid shopId);
}
public interface IProductAService : IProductService<ProductA>
{
//specifics to service A
}
public interface IProductBService : IProductService<ProductB>
{
//specifics to service B
}
But now you need to also pass the product type to the generic method, as I said - it gets slippery quickly (but maybe it'll do!)
public static async Task AddNewProducts<TProductService, TProduct>(Guid shopId)
where TProductService : IProductService<TProduct>
{
var productService = IoC.Services.GetService<TProductService<TProduct>>();
var added = await productService.AddProduct(shopId);
// Note "added" is of type TProduct
}
I call this situation "Generic hell". You are better of rethinking your design!
public static async Task AddNewProducts<T>(Guid shopId) where T : IProductAService, IProductBService
The problem with that line is that you're requiring T to implement both interfaces at once, not just one of them. You haven't even gotten to the errors that will spring up when you try to call this function, because presumably your class won't implement both.
Which leads me to question why you think you need to constrain your T like this. The only usage of T is to call Services.GetService<T>(), so the only constraint on it should be exactly the constraints that function requires, which are definitely not your two interfaces.

How to create and implement interfaces for operations that are only sometimes async

Let's say I have 100s of classes that implement a common interface with a method "calculate". Some of the classes will execute async (e.g. read a file), and other classes implementing the same interface will execute code that is sync (e.g. adding two numbers). What is a good way to code this, for maintenance and for performance?
The posts I read so far, always recommend to make async/await methods bubble up to the callers. So if you have one operation that is async, make the caller async, then its caller async, and so on. So this makes me think that the interface should be an async interface. However, this creates a problem when implementing the interface with code that is synchronous.
One idea I thought of is to expose in the interface 2 methods, one async and one sync, and one boolean property to tell the caller which method to call. This would look really ugly though.
The code I currently have is only one interface method that is async. Then for implementations that are synchronous, they wrap the code inside a Task object:
using System.IO;
using System.Threading.Tasks;
namespace TestApp
{
interface IBlackBox
{
Task<string> PullText();
}
sealed class MyAsyncBlackBox : IBlackBox
{
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
}
sealed class MyCachedBlackBox : IBlackBox
{
public Task<string> PullText()
{
return Task.Run(() => "hello world");
}
}
}
Is this the right approach to create and implement an interface that is only sometimes async? I have a lot of classes that implement short synchronous operations, and worry that this could add a lot of overhead. Is there some other way to do this that I am missing?
This is a common situation with interfaces. If you have a contract that needs to specify a task for the Async Await Pattern and we have to implement that Task in the interface.
Assuming the caller is going to use await you can just drop the async and return a Task.
However, you need to be-careful with your exceptions. It's assumed that exceptions are placed on the task. So to keep this plumbing the caller will expect you have to handle them slightly differently.
Common usages
Standard async
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
Returning a Task for CPU bound work (capturing the exception and placing it on the Task)
public Task<string> PullText()
{
try
{
return Task.Run(() => DoCpuWork());
}
catch (Exception e)
{
return Task.FromException<string>(e);
}
}
Slightly less efficient as we are plumbing an IAsyncStateMachine
public async Task<string> PullText()
{
return await Task.Run(() => DoCpuWork());
}
Returning a completed Task with a simple results (capturing the exception and placing it on the Task)
public Task<string> PullText()
{
try
{
// simplified example
return Task.FromResult("someString");
}
catch (Exception e)
{
return Task.FromException<string>(e);
}
}
There is also a 3rd approach, you can use the async keyword, and pragma out the warnings, this takes care of the error semantics for you. This feels a little dirty to me, just because it looks messy and the need to pragma out the warning, though I have now seen this used in bespoke production libraries
#pragma warning disable 1998
public async Task<string> PullText()()
#pragma warning restore 1998
{
return Task.Run(() => "hello world");
}
and
#pragma warning disable 1998
public async Task<string> PullText()()
#pragma warning restore 1998
{
return Task.FromResult("someString");
}
Note all the above deal with returning a Task<T> from the method. If one was just wanting to return the Task you can take advantage of Task.CompletedTask; with the same error semantics as above.
Usually in these cases, You have something in front of the call that is handling the request and passing it off to the "worker" classes (e.g. TestApp). If this is the case, I don't see why having an "IAsyncable" interface where you could test if the class was async capable would not work.
if(thisObject is IAscyncAble) {
... call the ansync request.
}
I ended up using the following code:
using System.IO;
using System.Threading.Tasks;
namespace TestApp
{
interface IBlackBox // interface for both sync and async execution
{
Task<string> PullText();
}
sealed class MyAsyncBlackBox : IBlackBox
{
public async Task<string> PullText()
{
using (var reader = File.OpenText("Words.txt"))
{
return await reader.ReadToEndAsync();
}
}
}
sealed class MyCachedBlackBox : IBlackBox
{
public Task<string> PullText() // notice no 'async' keyword
{
return Task.FromResult("hello world");
}
}
}

How do you implement chainable async extension methods?

I am wondering how to write chainable, async extension methods without requiring the caller to write multiple awaits and nested parentheses.
Example. Let's say your goal is for the caller to be able to write this sort of snippet:
var example = new MyCompilableClass();
await example.Compile().Run();
(Note: I'm not writing a compiler. I am just using these names to make it clear that one has to happen before the other).
To support the above, you create two interfaces:
public interface ICompilable
{
Task<IRunnable> CreateExecutableImage();
}
public interface IRunnable
{
Task Execute();
}
You implement them as async:
class SourceCode : ICompilable
{
public async Task<IRunnable> CreateExecutableImage()
{
await Stub.DoSomethingAsynchronous();
return new ObjectCode();
}
}
class ObjectCode : IRunnable
{
public async Task Execute()
{
await Stub.DoSomethingAsynchronous();
}
}
And then write the two extension methods with appropriate type constraints:
static class ExtensionMethods
{
public static async Task<IRunnable> Compile<T>(this T This) where T : ICompilable
{
return await This.CreateExecutableImage();
}
public static async Task Run<T>(this T This) where T : IRunnable
{
await This.Execute();
}
}
So now the caller tries to compile his code. But we get an error on this line:
await example.Compile().Run(); //Does not compile
Here is the compilation error:
The type 'System.Threading.Tasks.Task' cannot be used as type parameter 'T' in the generic type or method 'ExtensionMethods.Run(T)'. There is no implicit reference conversion from 'System.Threading.Tasks.Task' to 'Example.IRunnable'
We can fix the compilation error with parentheses:
(await example.Compile()).Run();
...or two lines of code:
var compiled = await example.Compile();
await compiled.Run();
...which both work. But that seems rather unfortunate if you were looking forward to a clean, chainable syntax as we have with LINQ.
Is there a different way to implement these extension methods, so that they keep their asynchronous nature, but without requiring the ugly syntax?
Here is a Link to DotNetFiddle if you'd like to work with my example code.
One simple answer is just to add another extension method that converts the Task<T> to a T, like this:
static class ExtensionMethods
{
public static async Task Run<T>(this T This) where T : IRunnable
{
await This.Execute();
}
public static async Task Run<T>(this Task<T> This) where T : IRunnable
{
////Await the task and pass it through to the original method
await (await This).Execute();
}
}
This will enable the caller to use
await example.Compile().Run();
...although he may have no idea he is passing the task, not the result, to Run() (unless he really thinks about it). Shouldn't matter to him.

Do I need to add async await if I am returning the return parameter of an async method? [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 5 years ago.
If I have a class that inherits a base class, and both classes inherit this interface
public interface BaseClass
{
Task<object> GetAsync();
}
If the base class implements its method as:
public async Task<object> GetAsync()
{
object o = async DoSomethingAsync();
return o;
}
And the class that inherits the base class overrides the method but calls the base class method still, does it matter if you put async await?
e.g?
// Option 1
public async Task<object> GetAsync()
{
DoSomethingElse();
return await base.GetAsync();
}
// Option 2
public Task<object> GetAsync()
{
DoSomethingElse();
return base.GetAsync();
}
What is the difference between the two? Is there any?
Despite it appearing to be part of the signature, async is in fact an implementation detail of the method that it decorates1. There is no need to decorate a method with async just because it's overriding a method that is implemented using it.
Option 2 is fine.
There's a github issue relating to automatically re-writing Option 1 to be Option 2, but I'm not sure if/when that will arrive, since there are some arguments against it (notably in the face of exceptions)
1As further evidence that it's not part of the signature, you're not even allowed to use async when defining interface members.
Calling base class method is no different than calling method from different class in this regard, you should still add 'await'. Without it your derived method will be executed synchronously.

Async programmic and virtual functions

If I have an interface such as:
using System.Threading.Tasks;
...
public interface IFoo
{
Task doIt();
Task<bool> doItAndReturnStuff();
}
and one of the classes implementing this interface just happens to not require async methods, how can i correct override these functions?
In other words, how do I correctly return "void" and "bool" wrapped in Task objects?
For example:
public class FooHappensToNotNeedAsync : IFoo
{
public override Task doIt()
{
// If I don't return anything here, I get
// error that not all code paths return a value.
// Can I just return null?
}
public override Task<bool> doItAndReturnStuff()
{
// If I want to return true, how to I do it?
// This doesn't work:
return true;
}
}
NOTE - I can't strip the Task stuff completely because some of the classes that implement this interface are in fact asynch.
Thanks
It's not clear what you're trying to achieve, but one approach (which would look the most like "normal" code) is probably just to make them async methods anyway:
public async Task DoIt()
{
// No-op
}
public async Task<bool> DoItAndReturnStuff()
{
return true;
}
Without any await expressions, the method will complete synchronously anyway. You'll get a warning on each method, but you could disable that just for this piece of code using a #pragma.
Alternatively - and I guess more simply in terms of not requiring a #pragma to disable warnings - would be to use Task.FromResult:
public Task DoIt()
{
// Returns a Task<bool>, but that's okay - it's still a Task
return Task.FromResult(true);
}
public Task<bool> DoItAndReturnStuff()
{
return Task.FromResult(true);
}

Categories

Resources