Why can't it figure out that my method returns an Task of IList<int>?
Because it doesn't. In this call:
Task.FromResult(new List<int>());
... type inference makes that equivalent to:
Task.FromResult<List<int>>(new List<int>());
So your method is trying to return a Task<List<int>> - and that's not compatible with Task<IList<int>>.
To simplify the point about Task<>, let's use string and object instead, and take out type inference and async entirely. The following code does not compile, and indeed shouldn't:
Task<string> stringTask = Task.FromResult<string>("text");
Task<object> objectTask = stringTask; // Doesn't compile
Task<T> is invariant - there's no conversion from Task<T1> to Task<T2> just because there's a conversion from T1 to T2.
You don't need an explicit cast though - you can just use the implicit conversion earlier:
public Task<IList<int>> TestAsync()
{
// It's important that this variable is explicitly typed as IList<int>
IList<int> result = new List<int>();
return Task.FromResult(result);
}
This uses the implicit conversion from List<int> to IList<int> for the result variable, and then it calls Task.FromResult<IList<int>> using type inference.
An alternative is to keep the method as it was before, except you specify the type argument for Task.FromResult:
public Task<IList<int>> TestAsync()
{
return Task.FromResult<IList<int>>(new List<int>());
}
>` is not a `Task>`.
– Lee Jul 30 '18 at 16:59