Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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.)

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.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top