Looping collections in C#
In this post I want to demonstrate that with a few nice language features in C# we can do more with less when working with collections, meaning expressing more with less code.
There are a couple of points I want to make here. First I care about writing code that can be easily understood after it is written. Secondly, I want to express as much as possible with as little as possible. I do not want to write five lines of code if I can express the same thing with just one line of code. These two concerns do of course relate. The keywords here are flexibility and efficiency. And let us not forget writing clean, expressive code is a lot more fun than fiddling with repetitive code: How many times have you written code (more than one line) to loop a collection? And how inspiring is it really? We want to loop those collections as easy as possible.
Languages like Python (and its relatives like Ruby and Boo) has put a lot of effort into making working with collections (or lists) as easy as possible. My main language at work nowadays is C#, and I must admit I envy developers in these languages when it comes to collections.
I actually envy them so much that I’ve been reflecting on how we can make our lives easier as well. With .Net 3.5 there is actually something we can do about it.
Collections in Python, Ruby and Boo
But first let me show you what I envy.
Let’s use a simple example to demonstrate my point: We have a list of numbers where we want to make a sub list with all the numbers bigger than 10. In addition, we do of course want to print the sub list to the console.
Boo (one of the most exiting languages for me these days) will simply do it this way:
numbers = [1,15,7,100,3,4,5,19] print numbers.Collect ({number as int| number>10})
In Boo, lists have built in functionality for making sub lists. I think this code is beautiful. The elegance (and often confusion for C#-developers not familiar with these kinds of languages) is how you declare the conditions for making the sub list. I won’t go into details about this but what we say here is: for the list “numbers”, take each “number” and add it to the sub list if “number>10″. The print statement is all you need to print the list (in an understandable human form) to the console.
It can’t be much simpler than this. Although I actually like the Ruby-way of doing this a micro-tad better:
numbers = [1,15,7,100,3,4,5,19] puts numbers.find_all{|number| number>10}
I like the find_all method name a bit better than Collect, and I like that you do not have to say “as int”. On the downside the “puts”-statement is a bit less intuitive than plain “print”. But in the long run these are details (or at least we can pretend it is in this context).
In python you can say it like this:
numbers = [1,15,7,100,3,4,5,19] print [number for number in numbers if number > 10]
Maybe a bit weirder at first glance, but it’s very concise if you’re used to it.
Ok, the point of this was to demonstrate that it is actually quite easy to express a loop very compact and elegant, and this is where I want to be when I loop collections in C#.
Looping collections in C#
The “this will work in almost any language”-code for doing the same job in C# will look something like this:
int[] numbers = new int[] { 1, 15, 7, 100, 3, 4, 5, 19 }; List<int> subset = new List<int>(); foreach (int number in numbers) { if (number > 10) subset.Add(number); } foreach (int number in subset) { Console.Write(number + " "); } Console.WriteLine();
It’s outright horrible compared to the Boo-example! It makes me wonder how many times longer it takes to develop a C#-application, and how much less readable it will be.
So what can we do? Well, let’s see if we can make it simpler.
Using delegates
With .Net 2.0, we were introduced to the concept of delegates (function pointers). It’s an odd concept for the traditional C#/vb/Java-developer. Function pointers are very common in some languages (again, typically in Python and friends), but not in “our” languages. Anyway, I’m really happy that Microsoft introduced us to this as it gives us some interesting possibilities.
We can remove a foreach-loop by using the Array.FindAll-method that takes a delegate. The delegate specifies how to filter the array, and then we have a sub list. This sounds a bit nicer. It looks like this:
int[] numbers = new int[] { 1, 15, 7, 100, 3, 4, 5, 19 }; int[] subset = Array.FindAll<int>(numbers, delegate(int number) { return number > 10; }); foreach (int number in subset) { Console.Write(number + " "); } Console.WriteLine();
Still a lot of code unfortunately, and the FindAll-method call isn’t really as clear and simple as it could have been either. I won’t go into details about the delegate-concept here, but if you do not understand how it works, I really advice you to take a look. It’s a powerful tool. (Look at my post Delegates, the interface for methods)
Using extension methods
The fact that you can just write “print” in Boo, where I have to write a foreach/Console.Write in C#, annoys me. Let’s fix it.
We could fix this by creating a subclass of Array, and override the ToString()-method. But frankly I do not like the idea. That would mean that everybody everywhere have to use that subclass instead of the standard Array-class. And that isn’t going to happen. There must be an easier way, and it is if you are fortunate enough to be working with .Net 3.0 . Here you can add an Extension Method to the Array-class. Unfortunately you cannot override a method by doing this (i.e. ToString), but you can create new methods on the Array. So let’s do that.
First the extension method:
public static class ArrayExtension { public static void Print(this int[] list) { foreach (int number in list) { Console.Write(number + " "); } Console.WriteLine(); } }
And then the main code:
int[] numbers = new int[] { 1, 15, 7, 100, 3, 4, 5, 19 }; int[] subset = Array.FindAll<int>(numbers, delegate(int number) { return number > 10; }); subset.Print(); // extension method
Look at that. I’m feeling better now. We’re getting somewhere.
Using Lambdas
I still do not like the delegate-declaration in the “FindAll”-method call. It’s clumsy, verbose, and not enough to the point. Lambdas introduced in .Net 3.0 will help us simplify this. Read more about lambdas here. For us, a lambda is just an easy way to declare a delegate. Look at this:
int[] numbers = new int[] { 1, 15, 7, 100, 3, 4, 5, 19 }; int[] subset = Array.FindAll<int>(numbers, number => number > 10 ); subset.Print();
Sweet! When you get used to it (and you should) the lambda-syntax is very easy to read. And look at how we do not have to declare the types anymore. I really like it. There can be a big difference between how you can do things, and how you should do things. I think this is how you should do it.
Using Linq
Actually, .Net introduces another elegant way to do this, Linq. It has quite a different syntax from most other languages with one notable exception: Sql. Linq treats almost anything like a collection that can be queried. Thus link is in itself a little dsl query language. It’s a great idea, I’ll give Microsoft that. Anyway, this is how our solution will look if we use Linq:
int[] numbers = new int[] { 1, 15, 7, 100, 3, 4, 5, 19 }; var subset = from n in numbers where n > 10 select n; subset.Print(); // new extension method
Yes, I like this one too. If you know Sql, and we probably all do, this is very easy to read.
Which one of these two do I like the most? To be honest, I’m not sure. I like them both. Feel free to give your thoughts on the issue.
Conclusion
To be honest I still like the Python/Ruby/Boo- way a little bit better, but with lambdas or linq I think C# is almost as elegant.
I want to make two points here:
First, it’s important to evaluate how we write code. We should always try to find ways to express more with less, and in this case we have been given several tools to help us on the way. It’s just up to us to use them, and use them well.
Secondly, do not let a language limit you. Try different languages and look at how they solve problems in different ways. Many times it will inspire you to find new and better ways to use a language, like here where we’ve applied a little pythonic thinking to C#.
- Tore Vestues


Bra blogg dette her, men blir det en øl snart?
August 27th, 2008 at 22:42 (988)Great post!
While reading it, I started thinking. Why is generic handled the way it is today for methods. Today we have to specify the parameter for the method, when in fact it could really figure this out by itself during compiletime by just looking at the types of the parameters using the type or the returntype.
I gotta get time to look at Boo, it looks so great. I must admit I find it more interesting than dynamic languages – I’m probably just conservative.
August 30th, 2008 at 20:04 (878)numbers.Select(n => n > 10).Print();
If I remember my linq correctly…
September 22nd, 2008 at 10:30 (479)