LINQ 中的延迟执行有什么好处? [英] What are the benefits of a Deferred Execution in LINQ?

查看:30
本文介绍了LINQ 中的延迟执行有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

LINQ 使用延迟执行模型,这意味着在调用 Linq 运算符时不会返回结果序列,而是这些运算符返回一个对象,该对象然后仅在我们枚举该对象时生成序列的元素.

LINQ uses a Deferred Execution model which means that resulting sequence is not returned at the time the Linq operators are called, but instead these operators return an object which then yields elements of a sequence only when we enumerate this object.

虽然我了解延迟查询的工作原理,但我在理解延迟执行的好处时遇到了一些麻烦:

While I understand how deferred queries work, I'm having some trouble understanding the benefits of deferred execution:

1) 我读过只有在您真正需要结果时才执行延迟查询会大有裨益.那么这个好处是什么呢?

1) I've read that deferred query executing only when you actually need the results can be of great benefit. So what is this benefit?

2)延迟查询的另一个好处是,如果你定义一次查询,那么每次枚举结果,如果数据发生变化,你会得到不同的结果.

2) Other advantage of deferred queries is that if you define a query once, then each time you enumerate the results, you will get different results if the data changes.

a) 但是从下面的代码中可以看出,即使不使用延迟查询,我们也能够达到相同的效果(因此每次枚举资源时,如果数据发生变化,我们会得到不同的结果):

a) But as seen from the code below, we're able to achieve the same effect ( thus each time we enumerate the resource, we get different result if data changed ) even without using deferred queries:

List<string> sList = new List<string>( new[]{ "A","B" });

foreach (string item in sList)
    Console.WriteLine(item); // Q1 outputs AB

sList.Add("C");

foreach (string item in sList)
    Console.WriteLine(item); // Q2 outputs ABC

3) 延迟执行还有其他好处吗?

3) Are there any other benefits of deferred execution?

推荐答案

主要好处是这使得过滤操作(LINQ 的核心)更加高效.(这实际上是您的第 1 项).

The main benefit is that this allows filtering operations, the core of LINQ, to be much more efficient. (This is effectively your item #1).

例如,以这样的 LINQ 查询为例:

For example, take a LINQ query like this:

 var results = collection.Select(item => item.Foo).Where(foo => foo < 3).ToList();

使用延迟执行,上面会迭代您的集合一次,并且在迭代期间每次请求一个项目时,执行映射操作、过滤器,然后使用结果来构建列表.

With deferred execution, the above iterates your collection one time, and each time an item is requested during the iteration, performs the map operation, filters, then uses the results to build the list.

如果每次都让 LINQ 完全执行,则每个操作 (Select/Where) 都必须遍历整个序列.这会使链式操作非常低效.

If you were to make LINQ fully execute each time, each operation (Select / Where) would have to iterate through the entire sequence. This would make chained operations very inefficient.

就我个人而言,我想说你上面的第 2 项更多的是副作用而不是好处 - 虽然它有时是有益的,但有时也会引起一些混乱,所以我只是认为这是理解"而不是吹捧它是 LINQ 的好处.

Personally, I'd say your item #2 above is more of a side effect rather than a benefit - while it's, at times, beneficial, it also causes some confusion at times, so I would just consider this "something to understand" and not tout it as a benefit of LINQ.

回应您的

在您的特定示例中,在这两种情况下,Select 都会迭代集合并返回 item.Foo 类型的 IEnumerable I1.Where() 然后将枚举 I1 并返回 item.Foo 类型的 IEnumerable<> I2.然后 I2 将被转换为 List.

In your particular example, in both cases Select would iterate collection and return an IEnumerable I1 of type item.Foo. Where() would then enumerate I1 and return IEnumerable<> I2 of type item.Foo. I2 would then be converted to List.

这不是真的 - 延迟执行可以防止这种情况发生.

This is not true - deferred execution prevents this from occurring.

在我的例子中,返回类型是IEnumerable,这意味着它是一个可以枚举的集合,但是,由于延迟执行,它不是实际上并没有列举出来.

In my example, the return type is IEnumerable<T>, which means that it's a collection that can be enumerated, but, due to deferred execution, it isn't actually enumerated.

当您调用 ToList() 时,将枚举整个集合.结果在概念上看起来更像是(尽管,当然,不同):

When you call ToList(), the entire collection is enumerated. The result ends up looking conceptually something more like (though, of course, different):

List<Foo> results = new List<Foo>();
foreach(var item in collection)
{
    // "Select" does a mapping
    var foo = item.Foo; 

    // "Where" filters
    if (!(foo < 3))
         continue;

    // "ToList" builds results
    results.Add(foo);
}

延迟执行导致序列本身仅被枚举(foreach)一次,当它被使用时(通过ToList()).如果没有延迟执行,它看起来更像是(概念上):

Deferred execution causes the sequence itself to only be enumerated (foreach) one time, when it's used (by ToList()). Without deferred execution, it would look more like (conceptually):

// Select
List<Foo> foos = new List<Foo>();
foreach(var item in collection)
{
    foos.Add(item.Foo);
}

// Where
List<Foo> foosFiltered = new List<Foo>();
foreach(var foo in foos)
{
    if (foo < 3)
        foosFiltered.Add(foo);
}    

List<Foo> results = new List<Foo>();
foreach(var item in foosFiltered)
{
    results.Add(item);
}

这篇关于LINQ 中的延迟执行有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆