推迟执行列表<;T>;使用Linq
假设我有一个推迟执行列表<;T>;使用Linq,linq,list,generics,deferred-execution,Linq,List,Generics,Deferred Execution,假设我有一个列表,其中包含1000项 然后我将其传递给筛选此列表的方法。 当它在各种情况下运行时(例如可能有50个),List最多可能有50个对其执行的各种LinqWhere()操作 我对尽快跑步感兴趣。因此,我不希望每次对该列表执行Where()时都对其进行过滤 基本上,我需要它来推迟对列表的实际操作,直到应用了所有过滤器 这是由编译器本机完成的吗?或者当我调用IEnumerable上的.ToList()时,List.Where()返回,或者我应该对X执行Where()操作(其中X=List.
列表
,其中包含1000项
然后我将其传递给筛选此列表的方法。
当它在各种情况下运行时(例如可能有50个),List
最多可能有50个对其执行的各种LinqWhere()
操作
我对尽快跑步感兴趣。因此,我不希望每次对该列表执行Where()
时都对其进行过滤
基本上,我需要它来推迟对列表的实际操作,直到应用了所有过滤器
这是由编译器本机完成的吗?或者当我调用IEnumerable上的.ToList()时,List.Where()
返回,或者我应该对X执行Where()
操作(其中X=List.AsQueryable())
希望这是有意义的。是的,本机支持延迟执行。每次在列表上应用查询或lambda表达式时,查询都会存储仅在对查询调用.ToList()时执行的所有表达式。是,本机支持延迟执行。每次在列表上应用查询或lambda表达式时,查询都会存储仅在对查询调用.ToList()时执行的所有表达式。每次调用,其中
将创建一个新对象,该对象了解您的过滤器及其调用顺序
当这个新对象被要求输入一个值时(我故意在迭代器和iterable之间搞模糊),它会要求原始序列输入下一个值,检查过滤器,然后返回值或迭代返回,要求原始序列输入下一个值等等
因此,如果您调用Where
50次(如在list.Where(…).Where(…).Where(…)
中),您最终得到的结果是,对于返回的每个项目,需要在调用堆栈中上下移动至少50次。这会对性能产生多大影响?我不知道:您应该衡量它
一种可能的替代方法是构建一个表达式树,然后在最后将其编译为委托,然后调用Where
。这当然需要付出更多的努力,但最终可能会更加高效。实际上,它可以让您改变这一点:
list.Where(x => x.SomeValue == 1)
.Where(x => x.SomethingElse != null)
.Where(x => x.FinalCondition)
.ToList()
进入
如果你知道你将要结合很多“where”一起过滤,这可能会比通过IQueryable
更有效。一如既往,在执行更复杂的操作之前,请检查最简单解决方案的性能。每次调用,其中
将创建一个新对象,该对象了解您的过滤器及其调用顺序
当这个新对象被要求输入一个值时(我故意在迭代器和iterable之间搞模糊),它会要求原始序列输入下一个值,检查过滤器,然后返回值或迭代返回,要求原始序列输入下一个值等等
因此,如果您调用Where
50次(如在list.Where(…).Where(…).Where(…)
中),您最终得到的结果是,对于返回的每个项目,需要在调用堆栈中上下移动至少50次。这会对性能产生多大影响?我不知道:您应该衡量它
一种可能的替代方法是构建一个表达式树,然后在最后将其编译为委托,然后调用Where
。这当然需要付出更多的努力,但最终可能会更加高效。实际上,它可以让您改变这一点:
list.Where(x => x.SomeValue == 1)
.Where(x => x.SomethingElse != null)
.Where(x => x.FinalCondition)
.ToList()
进入
如果你知道你将要结合很多“where”一起过滤,这可能会比通过IQueryable
更有效。一如既往,在做更复杂的事情之前,检查最简单的解决方案的性能。问题和评论中有太多的失败。答案很好,但没有足够的力度来突破失败
假设您有一个列表和一个查询
List<T> source = new List<T>(){ /*10 items*/ };
IEnumerable<T> query = source.Where(filter1);
query = query.Where(filter2);
query = query.Where(filter3);
...
query = query.Where(filter10);
List source=newlist(){/*10项*/};
IEnumerable query=source.Where(filter1);
query=query.Where(filter2);
query=query.Where(filter3);
...
query=query.Where(filter10);
[lazy evaluation]是由编译器本机完成的吗
不是。延迟评估是由于
此方法通过使用延迟执行来实现。立即返回值是一个存储执行操作所需的所有信息的对象。只有通过直接调用其GetEnumerator方法或使用Visual C#中的foreach或For Ea枚举该对象后,才会执行此方法表示的查询用visualbasic编程
呼叫列表中存在速度惩罚。AsQueryable().ToList()中
不要调用AsQueryable
,您只需要使用Enumerable.Where
因此不会阻止50个调用的深度调用堆栈
调用堆栈的深度远不如首先使用高效过滤器重要。如果您可以提前减少元素的数量,那么您可以在以后减少方法调用的数量。问题和注释中有太多的失败。答案很好,但没有足够的力度来突破失败
假设您有一个列表和一个查询
List<T> source = new List<T>(){ /*10 items*/ };
IEnumerable<T> query = source.Where(filter1);
query = query.Where(filter2);
query = query.Where(filter3);
...
query = query.Where(filter10);
List source=newlist(){/*10项*/};
IEnumerable query=source.Where(filter1);
query=query.Where(filter2);
query=query.Where(filter3);
...
query=query.Where(filter10);
[lazy evaluation]是由编译器本机完成的吗
不是。延迟评估是由于
此方法通过使用延迟执行来实现。立即返回值是一个存储执行操作所需的所有信息的对象。此方法表示的查询不是