Why do we need the `async` keyword? What is the difference between a function which returns a Task<int>, and an async function which returns a Task<int>?
Exactly, `async`/`await` is in the same realm of `yield`, it tells the compiler to take your code and create a state machine out of it. And also similarly to `foreach` and LINQ it boils down to a lot of duck typing.
There are two concepts:
1) _awaiters_ offer methods that the compiler-generated code will call to schedule continuations and ask whether it is completed. The thing that you call `await` on needs to offer a `GetAwaiter()` method that returns such an awaiter. (Due to the nature of the duck typing it might also be an extension method actually, so you can make types in other assemblies retrospectively awaitable)
2) _async method builders_ offer methods to perform the state machine transitions and connect them to the result object (which is traditionally of type `Task<T>` or `Task`). To register other types you can decorate them with the `System.Runtime.CompilerServices.AsyncMethodBuilderAttribute` attribute to tell the compiler what builder to use depending on the type you want to return in your async method.
An non-async Task<int> is returning a Task<int> object, where the return statement of an async Task<int> method is of type int (which will be wrapped in the resulting Task). ”return 1;” eg only works in the latter case.