I've been reading the source code of UserManager.cs and I've stepped into the following block:
public virtual Task<TUser> GetUserAsync(ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var id = GetUserId(principal);
return id == null ? Task.FromResult<TUser>(null) : FindByIdAsync(id);
}
I've been very curious if there is a reason why the above is not like this:
public virtual async Task<TUser> GetUserAsync(ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var id = GetUserId(principal);
return id == null ? await Task.FromResult<TUser>(null) : await FindByIdAsync(id);
}
As you can see I've only added async/await.
*I'm implementing the UserManager class with another ORM.
Since I didn't write it I cannot know for certain. ;) But I guess it's regarding the
return await
-anti pattern.There's even an issue for it on GitHub, where the request is that Roslyn handles it when compiling.
Optimize an async method that ends "return await e" to be non-async "return e"
To quote the excellent comment from damien_the_unbeliever, which he posted on this question
When using
await/async
one should be aware of the overhead it creates.Take these two classes for example:
If you decompile the code from
Bar
with ILSpy will look something like this:While
Foo
looks like this:So, to sum up, if you're simply going to return the value from one
Task
, there's really no reason toawait
it. Instead you should return theTask
and let the callerawait
thatTask
instead. Awaiting theTask
extends the stack and creates an overhead which only affects performance negatively.