Yes, Ruby and other dynamic languages are all the rage these days.
Yes, using Extension Methods in C# 3.0 is overplayed.
But you know what... I don’t care! So I’m going to show you an Extension Method that will bring a little Ruby-goodness to your hum-drum C# world.
The Ruby goodness
One of my favorite control structures in Ruby is the each method. This method can be used on any string, array, or hash to quickly iterate over each character of a string, item of an array, or key/value pair of a hash.
That’s not so special. What is special is that we can execute a block of code on each of those characters, items, or key/value pair, respectively.
1: heros = ['phil', 'rob', 'scott', 'the gu']
2:
3: heros.each do |hero|
4: puts "I have a hero named " + hero.capitalize
5: end
6:
7: # I have a hero named PHIL
8: # I have a hero named ROB
9: # I have a hero named SCOTT
10: # I have a hero named THE GU
Granted, that code is really simple, but the power is in the code block between the do and end keywords. That code block is similar to an anonymous method in C# parlance. Meaning, we can put as much, or little, code in there as needed. And each item being iterated over is passed into the block as a parameter between the pipes.
To review, the above is simply an array of strings. We’re iterating over the array, passing each string into code block via the hero parameter. And then the code block acts on the parameter do something with it. Pretty simple, yeah?
Get it in C#
C# 3.0 introduced a whole world of new and powerful methods for dealing with collections of... well of things. We can filter, search, order, and lots more. However, there’s not really a built-in way to iterate over the most basic of collection data types - the IEnumerable<T> interface.
Well, we do now!
1: public static void Each<T>(this IEnumerable<T> items, Action<T> action)
2: {
3: foreach (var item in items)
4: {
5: action(item);
6: }
7: }
Sure, the implementation is crazy simple, but it allows us to write far more expressive code and reduce some of the visual clutter that often gets in the way. Its all about solubility baby!
We can take lines 1-4 below, and collapse them into line 6.
1: foreach (String hero in heros)
2: {
3: System.Print("I have a hero named " + hero.ToUpper());
4: }
5:
6: heros.Each(hero => System.Print("I have a hero named " + hero.ToUpper()));
Or if we needed more than a single line of code, we could do something like
1: byte[] timestamp = new byte[len];
2: timestamp.Each(b =>
3: {
4: len--;
5: timestamp[len] = (byte) RandomInt();
6: });
Again, not exactly the most useful code in the world, but you can see where I’m going. If that code looks kinda' familiar, its because it is. :) I lifted it almost directly from my Value Type Parameters Are Still Value Types, Even in a Lambda Expression post.
So there you have it, some Ruby-esq deliciousness to help brighten a dreary statically-typed day in the world of C#. Boy, I loves me some Lambda expressions!