Ste*_*idi 10 .net c# task-parallel-library async-await
我正在寻找创建一个接受任何产生一个任务的函数IEnumerable<T>.为了说明,请考虑以下函数签名.
void DoWork<TElement>(Task<IEnumerable<TElement>> task)
{ }
Run Code Online (Sandbox Code Playgroud)
现在,我想将此方法称为如下:
Task<int[]> task = Task.FromResult(new[] { 1, 2, 3 });
DoWork(task);
Run Code Online (Sandbox Code Playgroud)
显然,这不起作用,因为两种Task类型不相同,并且任务不存在协方差.但是,我想知道是否有一些聪明的技巧可以让它工作,受以下例子的启发.
async Task<IEnumerable<int>> GetTask()
{
return await Task.FromResult(new int[] { 1, 2, 3 });
}
Run Code Online (Sandbox Code Playgroud)
这里,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);
Run Code Online (Sandbox Code Playgroud)
您可以再引入一个Type参数,并执行以下操作:
async Task<IEnumerable<TElement>> DoWork<T, TElement>(Func<Task<T>> getData,
Func<TElement, bool> predicate) where T : IEnumerable<TElement>
{
return (await getData()).Where(predicate);
}
Task<int[]> GetInts()
{
return Task.Run(() => new[] { 1, 2, 3 });
}
Task<long[]> GetLongs()
{
return Task.Run(() => new[] { 100L, 200L, 300L });
}
Run Code Online (Sandbox Code Playgroud)
然后你可以
static void Main()
{
var ints = DoWork<int[], int>(GetInts, i => i % 2 == 0).Result;
var longs = DoWork<long[], long>(GetLongs, i => i % 2 == 0).Result;
}
Run Code Online (Sandbox Code Playgroud)
或者如OP中的注释所述,如果TElement明确指定,可以使编译器推断出类型.
var ints = DoWork(GetInts, (int i) => i % 2 == 0).Result;
Run Code Online (Sandbox Code Playgroud)
您的代码不起作用,因为Task<T>不是"Covariant" T.您可能意识到类不能协变.
| 归档时间: |
|
| 查看次数: |
382 次 |
| 最近记录: |