EDIT Additional options and a slightly extended question below.
Consider this contrived and abstract example of a class body. It demonstrates four different ways of performing a “for” iteration.
private abstract class SomeClass
{
public void someAction();
}
void Examples()
{
List<SomeClass> someList = new List<SomeClass>();
//A. for
for (int i = 0; i < someList.Count(); i++)
{
someList[i].someAction();
}
//B. foreach
foreach (SomeClass o in someList)
{
o.someAction();
}
//C. foreach extension
someList.ForEach(o => o.someAction());
//D. plinq
someList.AsParallel().ForAll(o => o.someAction());
EDIT: Addition of some options from answers and research.
//E. ParallelEnumerable
ParallelEnumerable.Range(0, someList.Count - 1)
.ForAll(i => someList[i].someAction());
//F. ForEach Parallel Extension
Parallel.ForEach(someList, o => o.someAction());
//G. For Parallel Extension
Parallel.For(0, someList.Count - 1, i => someList[i].someAction())
}
My question comes in two parts. Have I missed some significant option? Which option is the best choice, considering readability but primarily performance?
Please indicate if the complexity of the SomeClass implementation, or the Count of someList would effect this choice.
EDIT: With such a dizzying array of options, I wouldn’t like my code to be spoilt by choice. To add a thrid part to my question, If my list could be any length should I default to a parallel option?
As a straw man. I suspect that over all implementations of SomeClass and all lengths of someList option //E. ParallelEnumerable would offer the best average performance, given the prevalanece of multi processor architechtures. I haven’t done any testing to prove this.
Note: The parallel extensions will require the use of the System.Threading.Tasks namespace.
Option A only really makes sense for sequences that implement indexing and will only be performant for those that have
O(1)lookup time. Generally, I would use theforeachand variants unless you have special logic.Also note, that “special logic” like
for (int i = 1; i < list.Count; i++)can be implemented with Linq extension methods:foreach(var item in sequence.Skip(1)).So, generally prefer B over A.
As to C: This can be confusing for other developers if they aren’t used to the functional style.
As to D: This will depend on a lot of factors. I guess for simple calculations, you don’t want to do this – you will only really benefit from parallelization if the loop body takes a while to compute.