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类似,只是它将返回一个生成器。生成器对象只遍历一次。

Yield有两个好处:

您不需要读取这些值两次; 您可以获得许多子节点,但不必将它们全部放在内存中。

还有一种解释也许能帮到你。

其他回答

那么这个呢?

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

        return products.ToList();
    }
}

我想这里干净多了。不过,我手头没有VS2008可以检查。 在任何情况下,如果Products实现了IEnumerable(似乎-它在foreach语句中使用),我将直接返回它。

假设您的产品LINQ类使用类似的yield来枚举/迭代,第一个版本更有效,因为它每次迭代只产生一个值。

第二个例子是使用ToList()方法将枚举器/迭代器转换为列表。这意味着它手动遍历枚举器中的所有项,然后返回一个平面列表。

yield的用法与关键字return类似,只是它将返回一个生成器。生成器对象只遍历一次。

Yield有两个好处:

您不需要读取这些值两次; 您可以获得许多子节点,但不必将它们全部放在内存中。

还有一种解释也许能帮到你。

这两段代码实际上在做两件不同的事情。第一个版本将根据需要拉成员。第二个版本将在您开始对其进行任何操作之前将所有结果加载到内存中。

这个问题没有对错之分。哪一种更可取取决于具体情况。例如,如果您必须在一定时间内完成查询,并且需要对结果执行一些半复杂的操作,那么第二个版本可能更可取。但是要注意大的结果集,特别是在以32位模式运行这段代码时。在使用这个方法时,我已经被OutOfMemory异常咬了好几次。

要记住的关键是:区别在于效率。因此,您可能应该使用任何使代码更简单的方法,并且只在分析之后更改它。

填充一个临时列表就像下载整个视频,而使用yield就像流媒体视频。