Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a generic type as a return type of an async method

A previous question made me wonder why the following method would raise a compile time error:

The return type of an async method must be void, Task or Task

public async T MyMethodAsync<T>() where T : Task
{
     // Irrelevant code here which returns a Task
}

Since we know at compile time that T is always a Task or a derived type, why won't this work?

Edit

The reason I'm asking is that a method may return a Task or a Task<T>. Let's say the method can return either and I don't want to duplicate code.

Of course this is all theoretical and isn't ment for production purposes.

Edit 2

Found a great article by Lucian Wischik: Why must async return Task

like image 519
Yuval Itzchakov Avatar asked May 29 '14 17:05

Yuval Itzchakov


People also ask

What is the return type of async method?

Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.

How do I return a task without await?

C# Language Async-Await Returning a Task without awaitThere is only one asynchronous call inside the method. The asynchronous call is at the end of the method. Catching/handling exception that may happen within the Task is not necessary.

Can async method return null?

Task represents the execution of the asynchronous method, so for an asynchronous method to return a null task is like telling the calling code "you didn't really just call this method" when of course it did. So, a Task / Task<T> returned from a method should never, ever be null .

Can I use task without async?

If you use await in your code, you are required to use the async keyword on the method. If you use async and want to return an actual type, you can declare that your method returns the type as a generic Task like this Task<int> . Task<TResult> , for an async method that returns a value.


Video Answer


1 Answers

Three problems:

  • Just because T is "Task or a derived type" doesn't mean that it's Task or Task<T>. What would you expect if I called MyMethodAsync<MyCustomTask> where MyCustomTask derives from Task?

  • The compiler needs to know whether it's building a state machine returning Task or Task<T> when it compiles the method - it uses different helper classes in the different cases

  • If an async method has a return type of Task, any return statements can't specify a value; if it has a return type of Task<T> any return statements must specify a value which is implicitly convertible to T. How can that work within MyMethodAsync? It's a bit like saying "my method is either void or returns a T - you can decide when you call it".

It's not clear what you're trying to achieve here, but basically this isn't going to work.

like image 134
Jon Skeet Avatar answered Oct 21 '22 15:10

Jon Skeet