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