Task.WhenAll With Different Types

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])
Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow