It should of course be generic so that you don't have to cast the values. You can use the Action delegate in the framwork instead of declaring your own.
public enum ForEachExecuction {
Concurrent,
Seperate
}
public static class ForEach<T> {
private static bool Call(Action<T> function, bool condition, T value, Action<T> concurrent) {
condition &= function != null;
if (condition) {
function(value);
if (concurrent != null) concurrent(value);
}
return condition;
}
public static void Loop(
IList<T> collection,
Action<T> function,
Action<T> before,
Action<T> first,
Action<T> evens,
Action<T> odds,
Action<T> last,
Action<T> after,
ForEachExecuction when)
{
Action<T> concurrent = when == ForEachExecuction.Concurrent?function:null;
for (int i = 0; i < collection.Count; i++) {
T value = collection[i];
Call(before, i == 0, value, null);
if (!Call(first, i == 0, value, concurrent)) {
if (!Call(evens, i % 2 != 0, value, concurrent)) {
if (!Call(odds, i % 2 == 0, value, concurrent)) {
if (!Call(last, i==collection.Count-1, value, concurrent)) {
function(value);
}
}
}
}
Call(after, i == collection.Count - 1, value, null);
}
}
}
Calling:
string[] testCollection = { "1", "2", "3", "4", "5" };
Action<string> primaryFunction = delegate(string s) { Console.WriteLine(s); }
Action<string> first = delegate(string s) { Console.WriteLine("first"); }
Action<string> odd = delegate(string s) { Console.WriteLine("odd"); }
Action<string> after = delegate(string s) { Console.WriteLine("after"); }
ForEach<string>.Loop(testCollection, primaryFunction, null, first, null, odd, null, after, ForEachExecuction.Concurrent);
Or perhaps:
ForEach<string>.Loop(testCollection,
(s) => Console.WriteLine(s),
null,
(s) => Console.WriteLine("first"),
null,
(s) => Console.WriteLine("odd"),
null,
(s) => Console.WriteLine("after"),
ForEachExecuction.Concurrent
);