2009-06-22 5 views
6

¿Cuál de estas soluciones se prefiere?C# declaraciones Linq o un foreach() para totalizar subconjuntos?

Para una lista:

List<ExampleInfo> exampleList = new List<ExampleInfo>(); 

public class ExampleInfo 
{ 
    internal ExampleInfo() 
    { } 
    /* Business Properties */ 
    public int Id { get; set; } 
    public string Type { get; set; } 
    public decimal Total { get; set; } 
} 

deseo de obtener subtotales con sede fuera del valor 'Total'.

Opción 1:

var subtotal1 = exampleList.Where(x => x.Type == "Subtype1").Sum(x => x.Total); 
var subtotal2 = exampleList.Where(x => x.Type == "Subtype2").Sum(x => x.Total); 

Opción 2:

decimal subtotal1 = 0m; 
decimal subtotal2 = 0m; 
foreach (ExampleInfo example in exampleList) 
{ 
    switch (example.Type) 
    { 
     case "Subtype1": 
      subtotal1 += example.Total; 
      break; 
     case "Subtype2": 
      subtotal2 += example.Total; 
      break; 
     default: 
      break; 

    } 
} 

La lista será < 10 artículos en la mayoría de los casos.

Editar: Chris planteó un muy buen punto que no mencioné. El programa ya está utilizando .NET Framework 3.5 SP1, por lo que la compatibilidad no es una consideración importante aquí.

Respuesta

4

Ambos ejemplos tienen código duplicado, y ambos no están listos para un cambio en Type, ¿y si tuviera tres valores? ¿Qué pasaría si tuviera 30?
usted podría utilizar LINQ para agrupar por ella y obtener el total:

var totals = from p in exampleList 
      group p by p.Type into g 
      select new { Type = g.Key, Total = g.Sum(p => p.Total) }; 

Así totals es una colección de objetos con las propiedades Type y Total

+0

Exactamente lo que estaba ocupado escribiendo al mismo tiempo :) –

+0

ja acabo de escribir el equivalente funcional –

2

No creo que haya mucha diferencia de rendimiento para listas tan pequeñas.

La opción 1 repetirá la lista dos veces, mientras que la opción 2 solo recorre la lista una vez. Puede ser más importante tener en cuenta para listas más grandes que las pequeñas.

La opción 1 es más fácil de leer, pero definitivamente me aseguraré de hacer un comentario que itere por la lista dos veces.

La ventaja obvia de la Opción 2 es que el código funciona en .NET Framework 2.0. El uso de LINQ significa que su aplicación requiere .NET Framework 3.5.

5

Independientemente del tamaño de la lista, si su objetivo es .NET 3.5 Me gustaría ir con LINQ, aunque solo sea por la legibilidad.

Soy un gran entusiasta de escribir lo que quiere decir, no cómo se hace y LINQ hace que esto sea muy fácil en tales casos.

Probablemente pueda incluso hacer los cálculos en una sola declaración LINQ, agrupando por Tipo. De esa manera usted no tendrá dos bucles para LINQ, pero sólo uno como en el segundo ejemplo:.

var subtotals = from x in exampleList 
       group x by x.Type into g 
       select new { Type = x.Key, SubTotal = g.Sum(x => x.Total) }; 

(No sabe con certeza si el código funciona, ya que, es sólo una rápida adaptación de uno de los 101 LINQ Samples de sintaxis debería estar bien, sin embargo).

1

Para la opción 1, internamente el bucle foreach será ejecutado dos veces por el entorno de tiempo de ejecución de C#. Por lo tanto, el tipo de procesamiento será más. Pero para < 10 elementos, apenas hace la diferencia, y la opción 1 parece más legible. Me gustaría ir con la opción 1 para < 10 artículos.

+0

El compilador de C# no se ejecuta el bucle en absoluto. Está hecho en tiempo de ejecución. –

+0

Gracias Jon. Cambió 'compilador' a 'env de tiempo de ejecución'. –

4

Opción 3

var groupings = exampleList 
    .GroupBy(x => x.Type, x => x.Total) 
    .Select(x => new { Type = x.Key, SubTotal = x.Sum() }); 

Vas a tener una lista de clases de este modo:

class <Anonymous> 
{ 
    public string Type { get; }  
    public decimal SubTotal { get; } 
} 

enumerar y asigne al valor adecuado, aunque podría ser excesiva para un pequeño conjunto tal.

Cuestiones relacionadas