A few days ago, a fellow programmer asked me a common question. How do you print odd numbers between one integer value and another. It's a common question and the quickest solution that came to mind is the common for loop with a simple if and the mod operator.
Later I began toying with the question and in combination wanted to experiment with an alternative to the limited ForEach extension method on IList<T>. What you see below is the result of a little tinkering and tweaking along with some fluent goodness.
I considered naming my custom extesion method ForEach but decided to use something different to remind myself that it is not your grandfather's ForEach extension method. So I named it ForEvery and in the middle of playing with that, I ended up creating the Once extension method on IEnumerable<T>.
class Program
{
static void Main(string[] args)
{
PrintOdds(1, 100);
Console.ReadLine();
}
static void PrintOdds(int x, int y)
{
Console.WriteLine("Odds with traditional for and if");
for (int i = x; i <= y; i++)
{
if (i % 2 != 0) Console.Write("{0}, ", i);
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Odds with ToList and ForEach with if");
Enumerable.Range(x, y - x + 1)
.ToList()
.ForEach(i =>
{
if (i % 2 != 0) Console.Write("{0}, ", i);
});
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Odds with Where then ToList and ForEach");
Enumerable.Range(x, y - x + 1).Where(n => n % 2 != 0)
.ToList().ForEach(i =>
{
Console.Write("{0}, ", i);
});
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Odds with Where and custom ForEach");
Enumerable.Range(x, y - x + 1)
.Where(n => n % 2 != 0)
.ForEach(i =>
{
Console.Write("{0}, ", i);
});
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Odds with custom ForEvery fluent");
Enumerable.Range(x, y - x + 1)
.ForEvery(n => n % 2 != 0, i =>
{
Console.Write("{0}, ", i);
})
.Once(n => n.Count() > 99, i =>
{
Console.WriteLine();
Console.WriteLine("Once fluent");
Console.WriteLine();
Console.WriteLine("Evens with ForEvery fluent from {0} to {1}", i.Min(), i.Max());
})
.ForEvery(n => n % 2 == 0, i =>
{
Console.Write("{0}, ", i);
});
}
}
public static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
{
action(item);
}
}
public static IEnumerable<T> Once<T>(this IEnumerable<T> collection,
Func<IEnumerable<T>, bool> predicate, Action<IEnumerable<T>> action)
{
if (predicate(collection)) action(collection);
return collection;
}
public static IEnumerable<T> ForEvery<T>(this IEnumerable<T> collection,
Func<T, bool> predicate, Action<T> action)
{
foreach (var item in collection)
{
if (predicate(item)) action(item);
}
return collection;
}
}
Drop the code into a console app and run it. If you like these little extensions, I'd love to hear from you.