tags:

views:

1150

answers:

5

Which of these solutions is preferred?

For a List:

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

I wish to get subtotals based off the 'Total' value.

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;

    }
}

The list will be <10 items in most cases.

Edit: Chris raised a very good point I did not mention. The program is already using .NET Framework 3.5 SP1 so compatibility isn't an important consideration here.

+2  A: 

I don't think there would be much performance difference for such small lists.

Option 1 will iterate through the list twice while Option 2 only iterates through the list once. That may be more important to note for larger lists than small ones.

Option 1 is more readable, but I would definitely make sure to make a comment that it iterates through the list twice.

The obvious advantage to Option 2 is that the code works in .NET Framework 2.0. Using LINQ means that your application requires .NET Framework 3.5.

Chris Thompson
+5  A: 

Regardless of list size, if you're targeting .NET 3.5 I'd go with LINQ, if only for readability.

I am a great fan of writing what you mean, not how it's done and LINQ makes this very easy in such cases.

You can probably even pull the calculations into a single LINQ statement, grouping by Type. That way you won't have two loops for LINQ but only one as in the second example:

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

(Not entirely sure whether the code works as it, it's just a quick adaption from one of the 101 LINQ Samples. Syntax should be ok, though.)

Joey
+1  A: 

For option1, internally the foreach loop will be executed twice by the C# run-time env. Hence processing type will be more. But for <10 items, it hardly makes any difference, and option 1 seems more readable. I would go with option 1 for < 10 items.

Rashmi Pandit
The C# compiler doesn't execute the loop at all. It's done at execution time.
Jon Skeet
Thanks Jon. Changed 'compiler' to 'run-time env'.
Rashmi Pandit
+4  A: 

Option 3

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

You'll have a list of classes like so:

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

Enumerate and assign to the appropriate value, although it might be overkill for such a small set.

Talljoe
+3  A: 

Both of these examples have duplicated code, and both aren't ready for a change on Type - what if it had three values? What if it had 30?
You could use linq to group by it and get the 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 ) };

So totals is a collection of objects with the properties Type and Total

Kobi
Exactly what I was busy typing at the same time :)
Jon Skeet
ha i just typed the functional equivalant
Sam Saffron