Cod*_*gue 19 c# linq lambda linq-to-objects
我在尝试使用async
lambda 时遇到以下错误IEnumerable.SelectMany
:
var result = myEnumerable.SelectMany(async (c) => await Functions.GetDataAsync(c.Id));
Run Code Online (Sandbox Code Playgroud)
无法从用法推断出方法'IEnumerable System.Linq.Enumerable.SelectMany(此IEnumerable,Func>)'的类型参数.尝试显式指定类型参数
在哪里GetDataAsync
定义为:
public interface IFunctions {
Task<IEnumerable<DataItem>> GetDataAsync(string itemId);
}
public class Functions : IFunctions {
public async Task<IEnumerable<DataItem>> GetDataAsync(string itemId) {
// return await httpCall();
}
}
Run Code Online (Sandbox Code Playgroud)
我想因为我的GetDataAsync
方法实际上返回了一个Task<IEnumerable<T>>
.但为什么Select
工作,肯定它应该抛出相同的错误?
var result = myEnumerable.Select(async (c) => await Functions.GetDataAsync(c.Id));
Run Code Online (Sandbox Code Playgroud)
有没有办法解决?
Ser*_*kiy 37
这是一个扩展:
public static async Task<IEnumerable<T1>> SelectManyAsync<T, T1>(this IEnumerable<T> enumeration, Func<T, Task<IEnumerable<T1>>> func)
{
return (await Task.WhenAll(enumeration.Select(func))).SelectMany(s => s);
}
Run Code Online (Sandbox Code Playgroud)
这允许你运行:
var result = await myEnumerable.SelectManyAsync(c => Functions.GetDataAsync(c.Id));
Run Code Online (Sandbox Code Playgroud)
说明:您有一个任务列表,每个返回Task<IEnumerable<T>>
.所以你需要解雇所有,然后等待所有,然后通过SelectMany压缩结果.
pwa*_*was 16
async lambda表达式无法转换为简单Func<TSource, TResult>
.
所以,选择很多都不能使用.您可以在同步上下文中运行:
myEnumerable.Select(c => Functions.GetDataAsync(c.Id)).SelectMany(task => task.Result);
Run Code Online (Sandbox Code Playgroud)
要么
List<DataItem> result = new List<DataItem>();
foreach (var ele in myEnumerable)
{
result.AddRange(await Functions.GetDataAsyncDo(ele.Id));
}
Run Code Online (Sandbox Code Playgroud)
你不能使用yield return
它 - 它是设计的.FE:
public async Task<IEnuemrable<DataItem>> Do()
{
...
foreach (var ele in await Functions.GetDataAsyncDo(ele.Id))
{
yield return ele; // compile time error, async method
// cannot be used with yield return
}
}
Run Code Online (Sandbox Code Playgroud)
Select
有效,因为它会返回一个IEnumerable<Task<T>>
,然后可以用 eg 等待它Task.WhenAll
。
因此,解决此问题的简单方法是:
IEnumerable<Task<IEnumerable<T>>> tasks = source.Select(GetNestedEnumerableTask);
IEnumerable<T>[] nestedResults = await Task.WhenAll(tasks);
IEnumerable<T> results = nestedResults.SelectMany(nr => nr);
Run Code Online (Sandbox Code Playgroud)
使用 C#8,IAsyncEnumerable
我们可以更自然地编写:
public static async IAsyncEnumerable<R> SelectManyAsync<T, R>(this IEnumerable<T> ts,
Func<T, Task<IEnumerable<R>>> func)
{
foreach (var t in ts)
{
var rs = await func(t);
foreach (var r in rs)
yield return r;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:用于await foreach(...
迭代IAsyncEnumerable
归档时间: |
|
查看次数: |
7327 次 |
最近记录: |