And*_*rew -1 c# generics asynchronous async-await
正如标题所述,我很好奇是否可以从 转换Task<List<Derived>>
为Task<List<BaseType>>
?
我有几个返回 的方法Task<List<Derived>>
,并且可以有多种类型的派生类。我想将所有任务存储在任务列表中:List<Task<List<BaseType>>>
稍后执行。
如果我的任务不是包装列表,这将非常简单:链接
编辑1
这是我遇到问题的部分,我在将任务存储在列表中时遇到问题:
// This throws an error (cannot convert derived list to base list)
var tasks = new List<Task<List<BaseType>>>
{
asyncThing1(), // returns Task<List<Derived1>>
asyncThing2(), // returns Task<List<Derived2>>
// ... n number more
};
// Need the list of tasks before I can execute
List<BaseType>[] results = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
编辑2
以上,List<Base>[]
改为List<BaseType>[]
正如标题所述,我很好奇是否可以从 转换
Task<List<Derived>>
为Task<List<Base>>
?
不。假设它是合法的,看看出了什么问题:
Task<List<Giraffe>> t1 = GetGiraffesAsync();
Task<List<Animal>> t2 = t1; // Suppose this were legal
(await t2).Add(new Fish());
Run Code Online (Sandbox Code Playgroud)
现在我们在长颈鹿列表中添加了一条鱼。
这三行之一必须是非法的。显然它不可能是第一个,因为GetGiraffesAsync
returns Task<List<Giraffe>>
。显然它不可能是最后一个,因为await t2
产生一个List<Animal>
,而鱼是一种动物。因此,非法的必定是中线。
现在,你可以这样做:
async Task<List<Animal>> ConvertAsync(Task<List<Giraffe>> t) =>
(await t).Select(g => (Animal)g).ToList();
Run Code Online (Sandbox Code Playgroud)
或者
async Task<List<Animal>> ConvertASync(Task<List<Giraffe>> t) =>
(await t).Cast<Animal>().ToList();
Run Code Online (Sandbox Code Playgroud)
或者
async Task<List<Animal>> ConvertAsync(Task<List<Giraffe>> t) =>
(await t).OfType<Animal>().ToList();
Run Code Online (Sandbox Code Playgroud)
如果你想让它通用你可以这样做
async Task<<List>Animal> ConvertAsync<T>(Task<List<T>> t) where T : Animal =>
(await t).OfType<Animal>().ToList();
Run Code Online (Sandbox Code Playgroud)
现在它适用于长颈鹿、鱼和老虎等。
也就是说,您可以异步等待原始任务完成,完成后,您可以从长颈鹿列表中创建新的动物列表。这是完全合法的。现在您有两个列表,一份是长颈鹿,一份是动物。
或者,你可以这样做:
async Task<IEnumerable<Animal>> ConvertAsync(Task<List<Giraffe>> t) =>
await t;
Run Code Online (Sandbox Code Playgroud)
因为List<Giraffe>
可转换为IEnumerable<Animal>
.
我倾向于将其写为扩展方法。
static class Extensions {
public static Task<List<Animal>> ConvertAsync<T>(
this Task<List<T>> t) where T : Animal {
return (await t).OfType<Animal>().ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
现在你的程序片段是:
var tasks = new List<Task<List<Animal>>>
{
GetGiraffesAsync().ConvertAsync(),
GetTigersAsync().ConvertAsync()
};
Run Code Online (Sandbox Code Playgroud)