我正在尝试优化一个看起来像这样(简化)的例程:
public async Task<IEnumerable<Bar>> GetBars(ObjectId id){
var output = new Collection<Bar>();
var page = 1;
var hasMore = true;
while(hasMore) {
var foos = await client.GetFoos(id, page);
foreach(var foo : foos) {
if(!Proceed(foo)) {
hasMore = false;
break;
}
output.Add(new Bar().Map(foo)
}
page++;
return output;
}
调用
GetBars()
的方法看起来像这样public async Task<Baz> GetBaz(ObjectId id){
var bars = await qux.GetBars();
if(bars.Any() {
var bazBaseData = qux.GetBazBaseData(id);
var bazAdditionalData = qux.GetBazAdditionalData(id);
return new Baz().Map(await bazBaseData, await bazAdditionalData, bars);
}
}
GetBaz()
返回 0 到很多项目。由于我们运行了几百万个 id,我们最初添加了 if(bars.Any())
语句作为加速应用程序的初步尝试。由于等待
GetBars()
,它会阻塞线程,直到它收集了所有数据(这可能需要一些时间)。我的想法是使用 yield return 然后用检查替换 if(bars.Any())
以测试我们是否至少获得一个元素,这样我们就可以同时触发另外两个异步方法(这也需要一些时间来执行)。我的问题是如何做到这一点。我知道
System.Linq.Count()
和 System.Linq.Any()
打败了 yield 返回的整个想法,如果我检查可枚举中的第一项,它将从可枚举中删除。除了向
GetBars()
添加例如 out 参数之外,还有其他/更好的选择吗?TL;DR:如何在不开始迭代的情况下检查来自 yield 返回的枚举是否包含任何对象?
最佳答案
对于您的实际问题“如何在不开始迭代的情况下检查来自 yield 返回的枚举是否包含任何对象?”好吧,你没有。
就是这么简单,你不能用句号,因为你可以用 IEnumerable 做的唯一一件事就是枚举它。调用 Any() 不是问题,因为它“确实”只枚举第一个元素(而不是整个列表),但不可能枚举任何内容,因为除了 a管道(可能没有后备集合,不可能检查不存在的东西是否有任何元素,设计上这是没有意义的)
编辑:另外,我在您的代码中没有看到任何 yield ,您是否混淆了 awaitable 和 yield 概念(完全不相关)?
关于c# - 检查 yield 返回是否包含项目,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26843222/