I have the follow program:
async Task Main()
{
IList<int> myList = await TestAsync();
}
public Task<IList<int>> TestAsync()
{
return Task.FromResult(new List<int>());
}
The compiler complains that it can't convert a Task<List>
to a Task<IList>
in the TestAsync
method:
CS0029 Cannot implicitly convert type
System.Threading.Tasks.Task<System.Collections.Generic.List<int>>
toSystem.Threading.Tasks.Task<System.Collections.Generic.IList<int>>
Why can't it figure out that my method returns an Task of IList?
The FromResult method returns a finished Task<TResult> object that holds the provided value as its Result property. This method is useful when you perform an asynchronous operation that returns a Task<TResult> object, and the result of that Task<TResult> object is already computed.
Gets a task that has already completed successfully. public: static property System::Threading::Tasks::Task ^ CompletedTask { System::Threading::Tasks::Task ^ get(); };
The recommended return type of an asynchronous method in C# is Task. You should return Task<T> if you would like to write an asynchronous method that returns a value. If you would like to write an event handler, you can return void instead. Until C# 7.0 an asynchronous method could return Task, Task<T>, or void.
To return Boolean from Task Synchronously, we can use Task. FromResult<TResult>(TResult) Method. This method creates a Task result that's completed successfully with the specified result. The calling method uses an await operator to suspend the caller's completion till called async method has finished successfully.
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>());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With