【发布时间】:2014-12-17 08:56:25
【问题描述】:
我正在寻找一个函数来接受任何产生IEnumerable<T> 的任务。为了说明,请考虑以下函数签名。
void DoWork<TElement>(Task<IEnumerable<TElement>> task)
{ }
现在,我想这样调用这个方法:
Task<int[]> task = Task.FromResult(new[] { 1, 2, 3 });
DoWork(task);
显然,这不起作用,因为这两个 Task 类型不一样,并且任务不存在协方差。但是,我想知道是否有一些聪明的技巧可以让它发挥作用,受以下示例的启发。
async Task<IEnumerable<int>> GetTask()
{
return await Task.FromResult(new int[] { 1, 2, 3 });
}
在这里,await 正在使用内联任务的结果有效地创建一个新任务,因此产生了类型转换的错觉。
举一个更详细的例子,我想允许用户拨打DoWork而不会给转换带来太多负担:
// Service proxy method
Task<int[]> GetInts()
{
// simplified for brevity
return Task.FromResult(new[] { 1, 2, 3 });
}
// Service proxy method
Task<long[]> GetLongs()
{
// simplified for brevity
return Task.FromResult(new[] { 100L, 200L, 300L });
}
async Task<IEnumerable<T>> DoWork<T>(Func<Task<IEnumerable<T>>> getData,
Func<T, bool> predicate)
{
return (await getData()).Where(predicate);
}
// GOAL:
DoWork(GetInts, i => i % 2 == 0);
DoWork(GetLongs, l => l % 40 == 0);
【问题讨论】:
-
我不认为这是一个重复的问题。我知道
Task<>不是协变的;我在问是否有一个聪明的语法或声明可以完成协变本来可以做的事情。 -
比如
dynamic? -
我怀疑
dynamic确实会解决所有类型匹配问题,但我希望先找到一个静态类型的解决方案。
标签: c# .net task-parallel-library async-await