tags:

views:

142

answers:

6

I am thinking about a re-factor, but I don't know if the end result is just overkill. Currently I have

    IList<myobjecttypebase> m_items;

   public int GetIncrementTotal()
   {
     int incrementTot;
     foreach(myobjecttypebase x in m_items)
     { incrementTot += x.GetIncrement(); }
   }

Would it be overkill and/or less efficient to use linq for the ForEach

m_items.ToList().ForEach(x => incrementTot += x.GetIncrement());

Would the cast be a significant overhead here?

+3  A: 

The overhead will be in iterating the collection twice.

m_items.ToList() // First iteration to add to the list all the items
   .ForEach(x => incrementTot += x.GetIncrement()); /* Second iteration to
                                                       perform logic */

ToList doesn't perform the iteration in lazy manner as most LINQ statements, therefor it will force the code iterate over the collection twice.

In general the LINQ form seems nicer to read, but if you're worrying about performance you better avoid it.

Elisha
I am assuming that the linq version would be the one with the overhead. If so would why would the ToList() method need to iterate the over the enumeration to cast from an IList
Andrew
@Andrew - Because it needs to convert the collection to a List<T>.
Oded
@Andrew: The ToList() method isn't a cast. It's a conversion method and will allocate and populate a new List<> object.
Binary Worrier
+8  A: 

Why not use the SUM operator directly on the IList?

It does have several overloads using Func delegates:

m_items.Sum(x => x.GetIncrement());
Oded
the GetIncrement method is an abstract method on the base class and different concrete implementations override the increment value. Otherwise I would have just used .Count() on the IList
Andrew
Doesn't change the answer...
Oded
I see your point thanks to John's code sample below.
Andrew
+1  A: 

Don't do it this way.
The ToList() here will allocate and populate a new list, IMHO not necessary. While it's a trivial exercise to write a ForEach extension method to iterate over any object that implements IEnumberable, I'd advise against it (see this article by Eric Lippert foreach V's ForEach).

I'd go with the foreach.

P.S. you need to initialise incrementTot (sorry, I couldn't help myself)

Binary Worrier
+2  A: 

As Oded mentioned use SUM

incrementTot = m_items.ToList().Sum(x => x.GetIncrement());
John Nolan
Why bother creating a list if all you're going to do is sum the values?
Jon Skeet
Thanks for the example. I didn't get what Oded meant as I am relatively new to linq.
Andrew
Jon skeet is right for once. ToList is superfluous.
John Nolan
+3  A: 

ForEach isn't part of LINQ - it's part of the List<T> API and has been since .NET 2.0.

The reason it's not part of LINQ is that it's a naturally side-effecting method... and LINQ doesn't encourage side-effects.

Using Sum is the right solution here, but you don't need to create a list first:

return m_items.Sum(x => x.GetIncrement());
Jon Skeet
+4  A: 

The ToList method is an extension method used with LINQ, but the ForEach method is just a method in the List class.

The major overhead here is the call to the ToList method, which creates a new List from the collection. The ForEach also has a slight overhead as it has to call a delegate for each item.

If you want to use LINQ methods, the Aggregate method seems more appropriate:

public int GetIncrementTotal() {
  return m_items.Aggregate(0, (t, i) => t + i.GetIncrement());
}

Or Sum:

public int GetIncrementTotal() {
  return m_items.Sum(i => i.GetIncrement());
}

Either has a slight overhead over your original version, so if you want the most efficient, just stick to a simple loop.

Guffa
Thanks for the comprehensive answer Guffa.
Andrew
The "slight overhead" here is just the difference between calling a delegate and inline code. Unless the collection is huge, or you are summing many collections using this as a basis for coding choices falls into the area of premature optimisation. Make changes like this only if performance testing shows you will get a significant improvement to your total run time.
Richard