Ruby-style Array methods in C# 3.0
A while back I played with Ruby-style loops in C# 3.0. This sparked my jealousy of other fun Ruby constructs that I couldn’t find in C#, and a couple of them are the “each” and “each_with_index” methods for arrays. Here’s an example, from thinkvitamin.com:
my_vitamins = ['b-12', 'c', 'riboflavin'] my_vitamins.each do |vitamin| puts "#{vitamin} is tasty!" end => b-12 is tasty! => c is tasty! => riboflavin is tasty!
With both Arrays and List
string[] myVitamins = {"b-12", "c", "riboflavin"}; Array.ForEach(myVitamins, (vitamin) => { Console.WriteLine("{0} is tasty", vitamin); } ); var myOtherVitamins = new List<string>() { "b-12", "c", "riboflavin" }; myOtherVitamins.ForEach( (vitamin) => { Console.WriteLine("{0} is very tasty", vitamin); } );
There are a few problems with these implementations, however:
- Inconsistent between types
- IEnumerable
left out - Array has a static method, whereas List
is instance - Index is unknown</ul>
Since T[] implicitly implements IEnumerable
, we can create a simple extension method to handle any case.
Without index
I still like the “Do” keyword in Ruby to signify the start of a block, and I’m not a fan of the readability (or “solubility”, whatever) of the “ForEach” method. Instead, I’ll borrow from the loop-style syntax I created in the previous post that uses a “Do” method:
myVitamins.Each().Do( (vitamin) => { Console.WriteLine("{0} is tasty", vitamin); } );
- Index is unknown</ul>
Since T[] implicitly implements IEnumerable
- Array has a static method, whereas List
- IEnumerable
</pre> </div>
To accomplish this, I’ll need something to add the “Each” method, and something to provide the “Do” method. Here’s what I came up with:
<div class="CodeFormatContainer">
<pre><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> RubyArrayExtensions {
<span class="kwrd">public</span> <span class="kwrd">class</span> EachIterator<T>
{
<span class="kwrd">private</span> <span class="kwrd">readonly</span> IEnumerable<T> values;
<span class="kwrd">internal</span> EachIterator(IEnumerable<T> values)
{
<span class="kwrd">this</span>.values = values;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Do(Action<T> action)
{
<span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> values)
{
action(item);
}
}
}
<span class="kwrd">public</span> <span class="kwrd">static</span> EachIterator<T> Each<T>(<span class="kwrd">this</span> IEnumerable<T> values)
{
<span class="kwrd">return</span> <span class="kwrd">new</span> EachIterator<T>(values);
} }
</pre> </div>
The “Each” generic method is an extension method that extends anything that implements IEnumerable<T>, which includes arrays, List<T>, and many others. IEnumerable<T> is ripe for extension, as .NET 3.5 introduced dozens of extension methods for it in the System.Linq.Enumerable class. With these changes, I now have a consistent mechanism to perform an action against an array or list of items:
<div class="CodeFormatContainer">
<pre><span class="kwrd">string</span>[] myVitamins = { <span class="str">"b-12"</span>, <span class="str">"c"</span>, <span class="str">"riboflavin"</span> };
myVitamins.Each().Do( (vitamin) => { Console.WriteLine(“{0} is tasty”, vitamin); } );
var myOtherVitamins = new List<string>() { “b-12”, “c”, “riboflavin” };
myOtherVitamins.Each().Do( (vitamin) => { Console.WriteLine(“{0} is very tasty”, vitamin); } ); </pre> </div>
### With index
Ruby also has a “each\_with\_index” method for arrays, and in this case, there aren’t any existing methods on System.Array or List<T> to accomplish this. With extension methods, this is still trivial to accomplish. I now just include the index whenever executing the callback to the Action<T, int> passed in. Here’s the extension method with the index:
<div class="CodeFormatContainer">
<pre><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> RubyArrayExtensions {
<span class="kwrd">public</span> <span class="kwrd">class</span> EachWithIndexIterator<T>
{
<span class="kwrd">private</span> <span class="kwrd">readonly</span> IEnumerable<T> values;
<span class="kwrd">internal</span> EachWithIndexIterator(IEnumerable<T> values)
{
<span class="kwrd">this</span>.values = values;
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Do(Action<T, <span class="kwrd">int</span>> action)
{
<span class="kwrd">int</span> i = 0;
<span class="kwrd">foreach</span> (var item <span class="kwrd">in</span> values)
{
action(item, i++);
}
}
}
<span class="kwrd">public</span> <span class="kwrd">static</span> EachWithIndexIterator<T> EachWithIndex<T>(<span class="kwrd">this</span> IEnumerable<T> values)
{
<span class="kwrd">return</span> <span class="kwrd">new</span> EachWithIndexIterator<T>(values);
} }
</pre> </div>
The only difference here is I keep track of an index to send back to the delegate passed in from the client side, which now looks like this:
<div class="CodeFormatContainer">
<pre><span class="kwrd">string</span>[] myVitamins = { <span class="str">"b-12"</span>, <span class="str">"c"</span>, <span class="str">"riboflavin"</span> };
myVitamins.EachWithIndex().Do( (vitamin, index) => { Console.WriteLine(“{0} cheers for {1}!”, index, vitamin); } );
var myOtherVitamins = new List<string>() { “b-12”, “c”, “riboflavin” };
myOtherVitamins.EachWithIndex().Do( (vitamin, index) => { Console.WriteLine(“{0} cheers for {1}!”, index, vitamin); } ); </pre> </div>
This now outputs:
<pre>0 cheers for b-12! 1 cheers for c! 2 cheers for riboflavin! 0 cheers for b-12! 1 cheers for c! 2 cheers for riboflavin!</pre>
### Pointless but fun
I don’t think I’d ever introduce these into production code, as it’s never fun to drop new ways to loop on other’s laps. If anything, it shows how even parentheses can hinder readability, even if the method names themselves read better.
In any case, I now have a simple, unified mechanism to perform an action against _any_ type that implements IEnumerable<T>, which includes arrays and List<T>.