Obtaining positional information in the IEnumerable Select extension method
- by Kyle Burns
This blog entry is intended to provide a narrow and brief look into a way to use the Select extension method that I had until recently overlooked. Every developer who is using IEnumerable extension methods to work with data has been exposed to the Select extension method, because it is a pretty critical piece of almost every query over a collection of objects. The method is defined on type IEnumerable and takes as its argument a function that accepts an item from the collection and returns an object which will be an item within the returned collection. This allows you to perform transformations on the source collection. A somewhat contrived example would be the following code that transforms a collection of strings into a collection of anonymous objects: 1: var media = new[] {"book", "cd", "tape"};
2: var transformed = media.Select( item =>
3: {
4: Media = item
5: } );
This code transforms the array of strings into a collection of objects which each have a string property called Media.
If every developer using the LINQ extension methods already knows this, why am I blogging about it? I’m blogging about it because the method has another overload that I hadn’t seen before I needed it a few weeks back and I thought I would share a little about it with whoever happens upon my blog. In the other overload, the function defined in the first overload as:
1: Func<TSource, TResult>
is instead defined as:
1: Func<TSource, int, TResult>
The additional parameter is an integer representing the current element’s position in the enumerable sequence. I used this information in what I thought was a pretty cool way to compare collections and I’ll probably blog about that sometime in the near future, but for now we’ll continue with the contrived example I’ve already started to keep things simple and show how this works. The following code sample shows how the positional information could be used in an alternating color scenario. I’m using a foreach loop because IEnumerable doesn’t have a ForEach extension, but many libraries do add the ForEach extension to IEnumerable so you can update the code if you’re using one of these libraries or have created your own.
1: var media = new[] {"book", "cd", "tape"};
2: foreach (var result in media.Select(
3: (item, index) =>
4: new { Item = item, Index = index }))
5: {
6: Console.ForegroundColor = result.Index % 2 == 0
7: ? ConsoleColor.Blue : ConsoleColor.Yellow;
8: Console.WriteLine(result.Item);
9: }