I am getting a compiler error for the following line of code:
IEnumerable<IPurchasedItem<IFruit>>[] result = await Task.WhenAll(
repository1.LoadItems(id),
repository2.LoadItems(id)
);
Error CS0029 Cannot implicitly convert type 'void' to
System.Collections.Generic.IEnumerable<IPurchasedItem<IFruit>>[]
My repository methods look like:
public async Task<IEnumerable<IPurchasedItem<Apple>>> LoadItems(int id) {}
public async Task<IEnumerable<IPurchasedItem<Orange>>> LoadItems(int id) {}
...where Apple
and Orange
descend from:
public interface IPurchasedItem<out T> : where T : IFruit {}
public class Fruit : IFruit {}
public class Apple : Fruit {}
public class Orange : Fruit {}
I've looked at this question, but it seems like I'm already doing what's suggested, i.e. asking for IEnumerable[]
rather than Task<IEnumerable>[]
.
What am I doing wrong - and if this isn't the right approach then what is the best way for me to await and combine the results of both LoadItems()
methods?
I was originally planning on doing:
result[0].Concat(result[1])
Task<T>
is a class, and therefore invariant. So a Task<string>
is not a Task<object>
- and as a more complicated example, a Task<IEnumerable<IPurchasedItem<Apple>>>
is not a Task<IEnumerable<IPurchasedItem<Fruit>>>
which is what you want it to be.
You could write a method to convert from one to another, of course - something like:
public static Task<TTarget> Convert<TSource, TTarget>(Task<TSource> task)
where TSource : TTarget
{
return await task;
}
Then you could convert all your specific tasks to Task<IEnumerable<IPurchasedItem<Fruit>>>
tasks instead, and then Task.WhenAll
will do what you want.
See more on this question at Stackoverflow