代码之家  ›  专栏  ›  技术社区  ›  Andrew

在这种情况下使用LINQ会造成过度杀伤力

  •  8
  • Andrew  · 技术社区  · 14 年前

    我正在考虑一个重新考虑的因素,但我不知道最终的结果是不是太致命了。 目前我有

        IList<myobjecttypebase> m_items;
    
       public int GetIncrementTotal()
       {
         int incrementTot;
         foreach(myobjecttypebase x in m_items)
         { incrementTot += x.GetIncrement(); }
       }
    

    前臂使用LINQ是否会过度杀伤力和/或效率降低?

    m_items.ToList().ForEach(x => incrementTot += x.GetIncrement());
    

    演员会是一个很大的开销吗?

    6 回复  |  直到 14 年前
        1
  •  4
  •   Guffa    14 年前

    ToList方法是用于Linq的扩展方法,但ForEach方法只是List类中的一个方法。

    这里的主要开销是对to list方法的调用,它从集合中创建一个新的列表。for each还有一点开销,因为它必须为每个项目调用委托。

    如果要使用LINQ方法,则聚合方法似乎更合适:

    public int GetIncrementTotal() {
      return m_items.Aggregate(0, (t, i) => t + i.GetIncrement());
    }
    

    或总和:

    public int GetIncrementTotal() {
      return m_items.Sum(i => i.GetIncrement());
    }
    

    任何一个都比您的原始版本稍有开销,所以如果您想要最有效的,只需坚持一个简单的循环。

        2
  •  7
  •   Oded    14 年前

    为什么不使用 SUM 直接在IList上操作?

    它确实有几个重载,使用 Func 代表:

    m_items.Sum(x => x.GetIncrement());
    
        3
  •  3
  •   Elisha    14 年前

    开销将在对集合进行两次迭代时产生。

    m_items.ToList() // First iteration to add to the list all the items
       .ForEach(x => incrementTot += x.GetIncrement()); /* Second iteration to
                                                           perform logic */
    

    托利斯特 不会像大多数LINQ语句那样以懒惰的方式执行迭代,因此它将强制代码在集合上迭代两次。

    一般来说,Linq表单似乎更适合阅读,但如果您担心性能问题,最好避免阅读。

        4
  •  3
  •   Jon Skeet    14 年前

    ForEach 不是Linq的一部分-它是 List<T> 从.NET 2.0开始。

    它不属于LINQ的原因是它是一种自然的副作用方法…Linq不鼓励副作用。

    在这里使用SUM是正确的解决方案,但您不需要首先创建列表:

    return m_items.Sum(x => x.GetIncrement());
    
        5
  •  2
  •   Johnno Nolan    14 年前

    如上文所述,使用和

    incrementTot = m_items.ToList().Sum(x => x.GetIncrement());
    
        6
  •  1
  •   Binary Worrier    14 年前

    别这样做。
    这个 ToList() 这里将分配和填充一个新列表,我不需要。 虽然编写foreach扩展方法来迭代实现IEnumerable的任何对象是一个很简单的练习,但是我建议不要这样做(参见本文,作者EricLippert) foreach V's ForEach )

    我会用前臂。

    另外,您需要初始化incrementtot(抱歉,我无法自拔)