Rob West
Rob West

Reputation: 5241

Why does removal of async/await cause conversion error for Task<T> to Task<object>

I have the following generic and non-generic methods:

public async Task<T> LoadAsync(Guid id)
{
    return await _someService.SomeMethodAsync(id);
}

async Task<object> LoadObjectAsync(Guid id) => await LoadAsync(id);

Trying to follow the advice from Stephen Cleary, I thought I'd make the code more efficient by removing the async/await from the LoadObjectAsync method as it is a passthrough. However, when I change the signature to:

Task<object> LoadObjectAsync(Guid id) => LoadAsync(id);

I get an error saying I cannot implicitly convert from Task<T> to Task<object>. What I'd like to know is how the async await avoids this conversion issue? I know that generic variance prohibits the conversion of the Task<> but why does this not apply to the async/await version?

Upvotes: 1

Views: 235

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456507

Trying to follow the advice from Stephen Cleary

The advice in that article is "leave the async/await in there unless you need to remove it". In this case, the method looks like a passthrough but is actually doing an implicit cast.

What I'd like to know is why the async await avoids this conversion issue?

With async and await, the code is casting T to object, which is always allowed.

Without async and await, the code is casting Task<T> to Task<object>, which is not allowed. This is because classes cannot support generic variance, and there is no ITask<T> type.

Upvotes: 5

Related Questions