检查收益率回报是否包含项目

时间:2014-11-10 11:51:55

标签: c# yield-return null-check

我正在尝试优化看起来像这样(简化)的例程:

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()违背了收益率返回的整个想法,如果我检查可枚举中的第一项,它就会从可枚举中删除。

除了向GetBars()添加例外参数外还有其他/更好的选择吗?

TL; DR:如何检查yield return中的枚举是否包含任何对象而不开始迭代它?

1 个答案:

答案 0 :(得分:4)

对于您的实际问题&#34;如何检查yield return中的可枚举是否包含任何对象而不开始迭代它?&#34;好吧,你不要。

这很简单,你可以不用时间,因为你可以用IEnumerable做的唯一事情就是枚举它。然而,调用Any()并不是一个问题,因为&#34;是&#34;只列举第一个元素(而不是整个列表),但不可能枚举任何东西,因为除了管道之外没有任何形式的任何形式都不存在(可能没有支持集合,它是不可能检查某些不存在的东西是否有任何元素,按照设计这没有任何意义)

编辑:此外,我还没有看到您的代码中有任何收益,您是否混淆了等待和屈服概念(完全不相关)?