Robert
Robert

Reputation: 1708

LINQ object aggregation

I often see this kind of piece of code as an example of aggregating object enumerables in c#:

IEnumerable<MyCoolObject> myObjects = new List<MyCoolObject>()
{new MyCoolObject(){Value1=1, Value2=10}, new MyCoolObject(){Value1=2, Value2=20}};
MyCoolObject aggregatedObject = myObjects.Aggregate(new MyCoolObject(), (accumlator, next) => new MyCoolObject()
{ 
    Value1=accumlator.Value1 + next.Value1, 
    Value2=accumlator.Value2 + next.Value2
}

My problem with this approach is it creates a new MyCoolObject every iteration, wich seems like a huge waste.

The other common example is this:

MyCoolObject aggregatedObject = new MyCoolObject()
{
    Value1=myObjects.Sum(x=>x.Value1),
    Value2=myObjects.Sum(x=>x.Value2)
}

This one iterates my collection twice, also a big waste, espetially, if there are more fields to aggregate on my objects.

What I figured is, I could do this:

MyCoolObject aggregatedObject = myObjects.Aggregate(new MyCoolObject(), (accumlator, next) =>
{ 
    accumlator.Value1 += next.Value1;
    accumlator.Value2 += next.Value2;
    return accumlator;
};

This one creates a single accumlator object, works on it, and returns it, when finished. To me this looks to be on par with a manual foreach loop performance-wise. I'm surprised, that I don't see this solution often. Are there any problems this solution can introduce, that could explain this?

Upvotes: 1

Views: 180

Answers (1)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131423

The common usage is to modify the accumulator and then return it, not to create a new object. In this case, I'd expect to see the following code:

var aggregatedObject = myObjects.Aggregate(new MyCoolObject(),
    (accumulator, next) => {
       accumulator.Value1 +=next.Value1;
       accumulator.Value2 +=next.Value2;
       return accumulator;
    });

Returning a new object from the accumulating function makes sense only if modifying the accumulator has side effects. A good accumulator object though should not produce side effects. In such a case it would be better to use a different object type as the accumulator.

Upvotes: 2

Related Questions