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