Categories: C#, LInQ
Posted by
mheydt on
10/30/2009 2:25 PM |
Comments (0)
I'm a big fan of Linq to objects. I really like the way that you can write much more concise code with it for every day things, not just things that you would think that you normally do with Linq.
One of the things that I almost always do now is use the Linq ForEach instead of the C# foreach statement. This gives you a nominal amount of code compression. But the thing I want to write about is using Linq instead of the C# 'for' statement, which I think leads to a lot nicer code.
I came across this the other day as I actually needed to write a 'for' statement to add a specific amount of nodes to a graph. Upon writing it, I was like 'gee, there must be a more concise way of doing this', such as where I don't need to do 'for', an initializer, comparison, and incrementation sub-statements. I mean, I just need to iterate across the integers 0 to 10 and apply a function to each.
The basic model that think of for doing this is provided in Ruby with sequences / ranges. As an example, here is some ruby that generates the integers 1 to 10 and prints each to the console:

I'm not going to explain ruby in detail, but the (1..10) generates the integers 1 to 10, the '.each' says for each item in the sequence apply the code block that follows. The code block is essentially a delegage with 'i' as a parameter and which prints 'i' to the console.
So how can this be done in C#? Well, it requires a couple of steps. First, System.Linq provides extensions to the Enumerable class, notably the 'Range' method which generates the values between two parameters:

This works fine, but I have an issue with it. Enumerable.Range (and most things in Linq) returns an IEnumerable. To iterate across those, you need to use the foreach statement (or a for, or while, that uses the IEnumerable methods), which is not really better than having to use the for loop. What I'd like is something still more concise.
One thing that can be done is to convert the enumerable to a list using the ToList() Linq extension method:

This works great, but I really don't like having to convert the result of .Range() to a list just so I can apply the .ForEach() method to the result. Why the Linq extensions don't have a .ForEach() on IEnumerable I don't know; it sure would be handy. But, we can write our own:

Now that we have this, we can rewrite the code to the following, which is what I've been looking for the whole time:

Perfect, concise, and also using a fluent interface that I really like.
c091a1f4-6441-4187-a5c3-c488092c33ff|0|.0