Происходит ли неявное преобразование между Task <> и int?
Нет. Это всего лишь часть того, как async/ awaitработает.
Любой метод, объявленный как, asyncдолжен иметь возвращаемый тип:
void (по возможности избегайте)
Task (нет результата, кроме уведомления о завершении / неудаче)
Task<T>(для логического результата типа Tасинхронно)
Компилятор выполняет все необходимые обертывания. Дело в том, что вы возвращаетесь асинхронноurlContents.Length - вы не можете заставить метод просто возвращаться int, поскольку фактический метод вернется, когда он попадет в первое awaitвыражение, которое еще не завершено. Поэтому вместо этого он возвращает, Task<int>который завершится, когда завершится сам асинхронный метод.
Обратите внимание, что awaitпроисходит обратное - он разворачивает a Task<T>в Tзначение, как работает эта строка:
string urlContents = await getStringTask;
... но, конечно, он разворачивает его асинхронно, тогда как простое использование Resultблокирует его до тех пор, пока задача не будет завершена. ( awaitможет разворачивать другие типы, реализующие ожидаемый шаблон, но Task<T>это тот, который вы, вероятно, будете использовать чаще всего.)
Эта двойная упаковка / развертывание - это то, что позволяет async быть настолько компонуемым. Например, я мог бы написать еще один асинхронный метод, который вызывает ваш и удваивает результат:
public async Task<int> AccessTheWebAndDoubleAsync()
{
var task = AccessTheWebAsync();
int result = await task;
return result * 2;
}
(Или просто return await AccessTheWebAsync() * 2;конечно.)
asyncключевого слова.