0

I simply want to add up values from a specific list of custom objects I am currently doing it like this:

private int CountChances()
{
    int totalChance = 0;
    foreach(var chance in this.Chances)
    {
       totalChance += chance.Value;
    }
    return totalChance;
}

Is there a way to do this faster without the foreach loop? I'm almost certain linq should be able to do this quickly but I cannot seem to find how to do it.

Vincent
  • 1,497
  • 1
  • 21
  • 44

2 Answers2

7

You can always do:

var sum = this.Chances.Sum(c => c.Value);

This is shorter and clearer coder. However, performance wise, the foreach might be just as fast or even faster.

Note, however, that the implementation of Sum uses checked mode, which can also affect the performance, so if your code is that critical, the foreach will be definitely faster.

However, we are talking about very fast code either way, if Chance is something like

class Chance {
    public long Value {get; set;}
}

and we have a list of 10 million items

var chances = Enumerable.Range(0, 10000000).Select(i => new Chance{Value = i});

on my machine, I'm getting 780ms for the foreach, and 1030ms for the Sum. So if your code goes nowhere near the million range, you're set with the Sum, as the code is way more obvious.

I.e. since your method is named CountChances, there's a chance that a support developer might mistake it's functioning, as it is not obvious at a glance that it actually sums the chances. No such chance with the Sum method.

Community
  • 1
  • 1
SWeko
  • 30,434
  • 10
  • 71
  • 106
  • Would be interesting to know if the difference was the same if you would materialize the query. `var chanceList=chances.ToList()`. Then measure the performance on `chanceList`. – Tim Schmelter Oct 29 '15 at 09:03
  • @TimSchmelter - for a materialized query, the result is 393ms vs 723ms in favor of the `foreach` – SWeko Oct 29 '15 at 09:08
  • @SWeko: still not sure what you have measured. Only one time with 10mio. items or many times? I'm suprised that the difference is so great. – Tim Schmelter Oct 29 '15 at 09:25
  • @TimSchmelter, One run, with a warmup round (in linqpad). I've run it multiple times, and did a manual average. https://gist.github.com/sweko/cddcc3dc97f38e3fbcf0 – SWeko Oct 29 '15 at 10:11
  • @SWeko: these are the results i get from your code, first two are loop and last two are `Enumerable.Sum`: `00:00:00.3780267 00:00:00.3770077 00:00:00.3931983 00:00:00.3159353` – Tim Schmelter Oct 29 '15 at 10:19
  • @TimSchmelter, weird. C# 6 compiler? – SWeko Oct 29 '15 at 11:15
5

You can do that like this:

this.Chances.Sum(e => e.Value);

Just include:

using System.Linq;
Aleksa
  • 2,976
  • 4
  • 30
  • 49