2010-02-03 22 views
8

Estoy pensando en un nuevo factor, pero no sé si el resultado final es simplemente exagerado. Actualmente tengoEstá usando linq en esta situación overkill

IList<myobjecttypebase> m_items; 

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

¿Sería excesivo y/o menos eficiente de utilizar LINQ para el ParaCada

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

¿El elenco ser una sobrecarga significativa aquí?

Respuesta

4

El método ToList es un método de extensión se utiliza con LINQ, pero el método ParaCada es sólo un método en la clase Lista.

La principal sobrecarga aquí es la llamada al método ToList, que crea una nueva lista de la colección. El ForEach también tiene una ligera sobrecarga, ya que tiene que llamar a un delegado para cada elemento.

Si desea utilizar métodos de LINQ, el método agregado parece más apropiado:

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

o Suma:

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

o bien tiene una ligera sobrecarga por encima de su versión original, así que si quieres el más eficiente, solo adhiérase a un simple bucle.

+0

Gracias por la respuesta completa Guffa. – Andrew

+0

La "ligera sobrecarga" aquí es solo la diferencia entre llamar a un delegado y un código en línea. A menos que la colección sea enorme, o si está sumando muchas colecciones usando esto como base para las opciones de codificación, cae en el área de la optimización prematura. Haga cambios como este solo si las pruebas de rendimiento muestran que obtendrá una mejora significativa en el tiempo total de ejecución. – Richard

3

La sobrecarga consistirá en iterar la colección dos veces.

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

ToList no realiza la iteración de manera perezosa como la mayoría de las declaraciones de LINQ, para ello se obligará a la iterate código a través de la colección dos veces.

En general, el formulario LINQ parece más agradable de leer, pero si te preocupa el rendimiento, es mejor que lo evites.

+0

Supongo que la versión de linq sería la que tiene los gastos generales. Si es así, ¿por qué el método ToList() necesita repetir la enumeración para lanzar desde un IList – Andrew

+0

@Andrew? Porque necesita convertir la colección a una lista . – Oded

+0

@Andrew: el método ToList() no es un elenco. Es un método de conversión y asignará y poblará un nuevo objeto List <>. –

7

¿Por qué no utilizar el operador SUM directamente en el IList?

Se tiene varias sobrecargas mediante Func delegados:

m_items.Sum(x => x.GetIncrement()); 
+0

el método GetIncrement es un método abstracto en la clase base y diferentes implementaciones concretas anulan el valor de incremento. De lo contrario, habría utilizado .Count() en el IList – Andrew

+0

No cambia la respuesta ... – Oded

+0

Veo su punto gracias al ejemplo de código de Juan a continuación. – Andrew

1

No hacerlo de esta manera.
El ToList() aquí asignará y rellenará una nueva lista, en mi humilde opinión no es necesario. Si bien es un ejercicio trivial escribir un método de extensión ForEach para iterar sobre cualquier objeto que implemente IEnumberable, recomendaría que no lo haga (consulte este artículo de Eric Lippert foreach V's ForEach).

I'd go with the foreach.

P.S. que necesita para inicializar incrementTot (lo siento, no pude evitarlo)

2

Como se ha mencionado Oded uso SUMA

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

¿Por qué molestarse en crear una lista si todo lo que vas a hacer es sumar los valores? –

+0

Gracias por el ejemplo. No entendí lo que Oded quería decir, ya que soy relativamente nuevo en linq. – Andrew

+0

Jon skeet es correcto por una vez. ToList es superfluo. –

3

ForEach no es parte de LINQ - es parte de la API List<T> y ha sido desde entonces. NET 2.0.

La razón por la que no forma parte de LINQ es porque es un método natural que causa efectos secundarios ... y LINQ no fomenta los efectos secundarios.

Usando suma es la solución aquí, pero no es necesario para crear una lista en primer lugar:

return m_items.Sum(x => x.GetIncrement()); 
Cuestiones relacionadas