LinQ 优化

Posted

技术标签:

【中文标题】LinQ 优化【英文标题】:LinQ optimization 【发布时间】:2011-02-26 14:16:22 【问题描述】:

下面是一段代码:

void MyFunc(List<MyObj> objects)

  MyFunc1(objects);

  foreach( MyObj obj in objects.Where(obj1=>obj1.Good))
  
    // Do Action With Good Object
  


void MyFunc1(List<MyObj> objects)

  int iGoodCount = objects.Where(obj1=>obj1.Good).Count();
  BeHappy(iGoodCount);

  // do other stuff with 'objects' collection

这里我们看到集合被分析了两次,每次检查每个成员的“好”属性的值:第一次计算好对象的计数,第二次 - 遍历所有好对象。

希望对其进行优化,这里有一个简单的解决方案:

在调用 MyFunc1 之前,makecreate 一个额外的临时集合只包含好的对象(goodObjects,它可以是 IEnumerable); 获取这些对象的计数并将其作为附加参数传递给 MyFunc1; 在“MyFunc”方法中迭代不是通过“objects.Where(...)”而是通过“goodObjects”集合。

方法还不错(据我所知),但需要在“MyFunc”方法中创建额外的变量,并且需要传递额外的参数。

问题:是否有任何 LinQ 开箱即用的功能允许在 1st Where().Count() 期间进行任何缓存,记住已处理的集合并在下一次迭代中使用它?

欢迎提出任何想法。

谢谢。

【问题讨论】:

【参考方案1】:

不,LINQ 查询没有以这种方式优化(您描述的方式类似于 SQL Server 重用查询执行计划的方式)。 LINQ 没有(并且,出于实际目的,无法)对您的对象了解得足够多,无法以这种方式进行优化。据它所知,您的收藏在两次调用之间发生了变化(或完全不同)。

您显然知道将查询保留到新的 List&lt;T&gt; 中的能力,但除此之外,如果不了解您的课程以及在哪里使用 MyFunc 的更多信息,我真的没有什么可以推荐的。

【讨论】:

【参考方案2】:

只要 MyFunc1 不需要通过添加/删除对象来修改列表,这将起作用。

void MyFunc(List<MyObj> objects)

  ILookup<bool, MyObj> objLookup = objects.ToLookup(obj1 => obj1.Good);
  MyFunc1(objLookup[true]);

  foreach(MyObj obj in objLookup[true])
  
    //..
  


void MyFunc1(IEnumerable<MyObj> objects)

  //..

【讨论】:

以上是关于LinQ 优化的主要内容,如果未能解决你的问题,请参考以下文章

如何优化这个 linq 查询?

LINQ 是不是使用 DataRelations 来优化连接?

优化 LINQ 查询所需的帮助

使用 EF6 优化 LINQ 查询

使用 LINQ 优化内存中慢查询列表以检索数据

这两个 LINQ 查询有啥区别以及如何正确优化它们?