正确使用“收益回报”

yield关键字是C#中的一个关键字,它继续使我神秘化,而且我从未确信我正确使用它。

以下两段代码中,哪些是首选的,为什么?

版本1:使用收益率回报

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        foreach (Product product in products)
        {
            yield return product;
        }
    }
}

版本2:返回列表

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        return products.ToList<Product>();
    }
}

当我计算列表中的下一个项目(甚至下一组项目)时,我倾向于使用yield-return。

使用你的版本2,你必须在返回之前有完整的列表。 通过使用yield-return,你只需要在返回之前拥有下一个项目。

除此之外,这有助于在更大的时间范围内传播复杂计算的计算成本。 例如,如果列表连接到GUI并且用户永远不会到最后一页,则永远不会计算列表中的最终项目。

如果IEnumerable表示无限集,另一种情况是yield-return更可取。 考虑素数列表,或随机数字的无限列表。 你永远不能一次返回完整的IEnumerable,所以你使用yield-return来递增返回列表。

在你的特定例子中,你有完整的产品列表,所以我会使用版本2。


填充临时列表就像下载整个视频一样,而使用yield则类似于流式传输视频。


作为理解何时应该使用yield的概念示例,假设方法ConsumeLoop()处理由ProduceList()返回/产生的项目:

void ConsumeLoop() {
    foreach (Consumable item in ProduceList())        // might have to wait here
        item.Consume();
}

IEnumerable<Consumable> ProduceList() {
    while (KeepProducing())
        yield return ProduceExpensiveConsumable();    // expensive
}

如果没有yield ,对ProduceList()的调用可能需要很长时间,因为您必须在返回之前完成列表:

//pseudo-assembly
Produce consumable[0]                   // expensive operation, e.g. disk I/O
Produce consumable[1]                   // waiting...
Produce consumable[2]                   // waiting...
Produce consumable[3]                   // completed the consumable list
Consume consumable[0]                   // start consuming
Consume consumable[1]
Consume consumable[2]
Consume consumable[3]

使用yield ,它会重新排列,并行工作:

//pseudo-assembly
Produce consumable[0]
Consume consumable[0]                   // immediately Consume
Produce consumable[1]
Consume consumable[1]                   // consume next
Produce consumable[2]
Consume consumable[2]                   // consume next
Produce consumable[3]
Consume consumable[3]                   // consume next

最后,如前所述,您应该使用版本2,因为您已经拥有完整的列表。

链接地址: http://www.djcxy.com/p/9097.html

上一篇: Proper use of 'yield return'

下一篇: Usefulness of yield