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

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

问题描述

LINQ使用Deferred Execution模型,这意味着在调用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();

使用延迟执行,上面的代码一次迭代您的集合 ,并且每次在迭代过程中请求一个项目,执行map操作,进行过滤,然后使用结果来构建列表.

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都会迭代collection并返回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<T>,这意味着它是一个可以枚举的集合,但是由于延迟执行,因此实际上并未枚举.

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);
}

延迟执行将导致序列本身在使用时(ToList())仅被枚举(foreach)一次 .如果不推迟执行,从概念上看,它看起来会更像:

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天全站免登陆