We have this method:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
//The thing is that this returns an int to a method that has a return type of Task<int>
return urlContents.Length;
}
Does an implicit conversion occur between Task<int>
and int
? If not, then what is happening? How is it implemented to work?
Does an implicit conversion occur between Task<> and int?
Nope. This is just part of how async
/await
works.
Any method declared as async
has to have a return type of:
void
(avoid if possible)Task
(no result beyond notification of completion/failure)Task<T>
(for a logical result of type T
in an async manner)The compiler does all the appropriate wrapping. The point is that you're asynchronously returning urlContents.Length
- you can't make the method just return int
, as the actual method will return when it hits the first await
expression which hasn't already completed. So instead, it returns a Task<int>
which will complete when the async method itself completes.
Note that await
does the opposite - it unwraps a Task<T>
to a T
value, which is how this line works:
string urlContents = await getStringTask;
... but of course it unwraps it asynchronously, whereas just using Result
would block until the task had completed. (await
can unwrap other types which implement the awaitable pattern, but Task<T>
is the one you're likely to use most often.)
This dual wrapping/unwrapping is what allows async to be so composable. For example, I could write another async method which calls yours and doubles the result:
public async Task<int> AccessTheWebAndDoubleAsync()
{
var task = AccessTheWebAsync();
int result = await task;
return result * 2;
}
(Or simply return await AccessTheWebAsync() * 2;
of course.)