不同类型的 Task.WhenAll

Geo*_*off 2 c# async-await

我收到以下代码行的编译器错误:

IEnumerable<IPurchasedItem<IFruit>>[] result = await Task.WhenAll(
                repository1.LoadItems(id),
                repository2.LoadItems(id)
                );
Run Code Online (Sandbox Code Playgroud)

错误 CS0029 无法将类型“void”隐式转换为 System.Collections.Generic.IEnumerable<IPurchasedItem<IFruit>>[]

我的存储库方法如下所示:

public async Task<IEnumerable<IPurchasedItem<Apple>>> LoadItems(int id) {}
public async Task<IEnumerable<IPurchasedItem<Orange>>> LoadItems(int id) {}
Run Code Online (Sandbox Code Playgroud)

...从哪里Apple开始Orange

public interface IPurchasedItem<out T> : where T : IFruit {}
public class Fruit : IFruit {}
public class Apple : Fruit {}
public class Orange : Fruit {}
Run Code Online (Sandbox Code Playgroud)

我已经看过这个问题,但似乎我已经在做建议的事情,即要求而IEnumerable[]不是Task<IEnumerable>[]

我做错了什么 - 如果这不是正确的方法,那么我等待并结合两种LoadItems()方法的结果的最佳方法是什么?我原本打算这样做:

result[0].Concat(result[1])
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

Task<T>是一个类,因此是不变的。所以 aTask<string>不是 a Task<object>- 作为一个更复杂的例子, aTask<IEnumerable<IPurchasedItem<Apple>>>不是Task<IEnumerable<IPurchasedItem<Fruit>>>你想要的 a 。

当然,您可以编写一种方法从一种方法转换为另一种方法 - 类似于:

public static Task<TTarget> Convert<TSource, TTarget>(Task<TSource> task)
    where TSource : TTarget
{
    return await task;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以将所有特定任务转换为Task<IEnumerable<IPurchasedItem<Fruit>>>任务,然后 Task.WhenAll你想做的事。

  • @Geoff:我已经告诉过你想要正确的方法是 - 在调用 `Task.WhenAll` 之前将单个任务转换为通用任务类型。因此,您可以调用“Convert&lt;Apple, Fruit&gt;(AppleFactory.LoadItems(...))”和“Convert&lt;Orange, Fruit&gt;(OrangeFactory.LoadItems(...))”,然后调用“Task.WhenAll”与两个结果。 (3认同)