Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why async method return type can not be derived from Task?

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>?

like image 209
Kimke Avatar asked Feb 06 '23 14:02

Kimke


2 Answers

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.

like image 93
Peter Duniho Avatar answered Feb 12 '23 10:02

Peter Duniho


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>();
        }
    }
like image 20
Backs Avatar answered Feb 12 '23 11:02

Backs