2009-06-22 4 views
6

Welche dieser Lösungen wird bevorzugt?C# Linq-Anweisungen oder eine Foreach() für die Summierung von Teilmengen?

Für eine Liste:

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; } 
} 

Ich wünsche Teilsumme den 'Total' Wert basierend auszusteigen.

Option 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); 

Option 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; 

    } 
} 

Die Liste wird < 10 Stück in den meisten Fällen sein.

Bearbeiten: Chris hob einen sehr guten Punkt, den ich nicht erwähnt habe. Das Programm verwendet bereits .NET Framework 3.5 SP1, daher ist Kompatibilität hier nicht wichtig.

Antwort

4

Beide Beispiele haben Code dupliziert, und beide sind nicht bereit für eine Änderung Type - was wäre, wenn es drei Werte hätte? Was wäre wenn es 30 hätte?
Sie könnten Linq zu Gruppe, indem sie es verwenden und die Gesamt erhalten:

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

So totals eine Sammlung von Objekten mit den Eigenschaften ist Type und Total

+0

Genau das, was ich zur gleichen Zeit tippte :) –

+0

Ich habe gerade das funktionale Äquivalent eingegeben –

2

Ich glaube nicht, dass es für solche kleinen Listen viel Leistungsunterschied wäre.

Option 1 durchläuft die Liste zweimal, während Option 2 nur einmal durch die Liste iteriert. Das kann für größere Listen wichtiger sein als kleine.

Option 1 ist besser lesbar, aber ich würde auf jeden Fall einen Kommentar machen, dass sie zweimal durch die Liste iteriert.

Der offensichtliche Vorteil von Option 2 ist, dass der Code in .NET Framework 2.0 funktioniert. Die Verwendung von LINQ bedeutet, dass Ihre Anwendung .NET Framework 3.5 erfordert.

5

Unabhängig von der Listengröße, wenn Sie auf .NET 3.5 ausgerichtet sind, würde ich mit LINQ gehen, wenn auch nur zur besseren Lesbarkeit.

Ich bin ein großer Fan des Schreibens, was Sie meinen, nicht wie es gemacht wird und LINQ macht dies in solchen Fällen sehr einfach.

Sie können die Berechnungen wahrscheinlich sogar in eine einzelne LINQ-Anweisung ziehen, die nach Typ gruppiert ist. Auf diese Weise werden Sie nicht zwei Schleifen für LINQ haben aber nur eine, wie im zweiten Beispiel.

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

(Nicht ganz sicher, ob der Code wie es funktioniert, es ist nur eine schnelle Anpassung von einem der 101 LINQ Samples Syntax sollte aber in Ordnung sein.)

1

Bei Option1 wird intern die foreach-Schleife zweimal von der C# Laufzeit env ausgeführt. Daher wird der Verarbeitungstyp mehr sein. Aber für < 10 Elemente macht es kaum einen Unterschied, und Option 1 scheint lesbarer. Ich würde mit Option 1 für < 10 Elemente gehen.

+0

Der C# -Compiler nicht bei allen die Schleife auszuführen. Es ist zur Ausführungszeit fertig. –

+0

Danke Jon. "Compiler" wurde in "Laufzeitumgebung" geändert. –

4

Option 3

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

Sie werden wie so eine Liste von Klassen haben:

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

Aufzählen und auf den entsprechenden Wert zuweisen, obwohl es viel des Guten für eine so kleine Menge sein könnte.