I have a class (simplified sample and only relevant parts shown)
public class AsyncScenario : Task<Scenario>
{
public async AsyncScenario Test(Func<Task> action)
{
return await this;
}
}
I can't compile this because the return type of the method:
Compiler error CS1983: "The return type of an async method must be void, Task or Task<T>"
Why is it not allowed for async method to return a class derived from Task<T>
?
Because the C# specification says so? Short of Eric Lippert or some other language design team person chiming in†, you're not going to get a better answer than that. Anything else would be pure speculation and opinion.
That said, given that in an async
method, the return value is implied by the return
statement, what do you think the specification rules should be in such an example? Clearly await this
resolves to a Scenario
object...how is the C# compiler supposed to synthesize a new AsyncScenario
object from that expression type?
I suppose you might come up with some additional rules you could put in the specification that would unambiguously provide for some mechanism. But it seems to me those rules would be significantly more complex than the rules that exist as the specification stands now, where the return type is always a type that is known to the spec author and has clear rules for creating the first time the method returns and, just as important, changing the state of when the return
statement is executed.
It seems likely to me that the rules exist as they do, simply because to do otherwise would require an inordinate amount of effort, and would dramatically increase the complexity of compilers and the likelihood of bugs in said compilers.
† Speaking of which, a little searching dug up gold: Why must async methods return Task?, written by Lucian Wischik, language designer for VB.NET (but the article is similarly applicable to C#). See also Jon Skeet's answer at Using a generic type as a return type of an async method.
You can await any method, that returns type with GetAwaiter method:
public static async Task<Scenario> Test()
{
return await new AsyncScenario();
}
public class AsyncScenario
{
public TaskAwaiter<Scenario> GetAwaiter()
{
return new TaskAwaiter<Scenario>();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With