Jacob Carpenter’s Weblog

November 24, 2007

Another set of extension methods

Filed under: csharp, extension methods, Ruby — Jacob @ 3:16 pm

In addition to the interesting diversions we’ve taken, I do want to continue presenting potentially useful code samples too. So here’s a fresh set of ruby inspired extensions:

public static IEnumerable<IndexValuePair<T>> WithIndex<T>(this IEnumerable<T> source)
{
    int position = 0;
    foreach (T value in source)
        yield return new IndexValuePair<T>(position++, value);
}    

public static void Each<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (T item in source)
        action(item);
}

public static void EachWithIndex<T>(this IEnumerable<T> source, Action<T, int> action)
{
    Each(WithIndex(source), pair => action(pair.Value, pair.Index));
}

I’ll include the mundane definition of IndexValuePair<T> (along with parameter validation) at the end of this post. But spend some time looking at these very simple methods.

diagram 1

Notice how once we’ve defined WithIndex and Each, we can combine them to define EachWithIndex. When we chain Each to the result of WithIndex, the type of the Action must be converted accordingly:

diagram 2

This is easily accomplished by the statement:

pair => action(pair.Value, pair.Index)

So with the added definition of IndexValuePair<T> and parameter validation, we add to our collection extensions the following:

using System;
using System.Collections.Generic;

public static class CollectionEx
{
    public static void Each<T>(this IEnumerable<T> source, Action<T> action)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (action == null)
            throw new ArgumentNullException("action");

        foreach (T item in source)
            action(item);
    }

    public static void EachWithIndex<T>(this IEnumerable<T> source, Action<T, int> action)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        if (action == null)
            throw new ArgumentNullException("action");

        Each(WithIndexIterator(source), pair => action(pair.Value, pair.Index));
    }

    public static IEnumerable<IndexValuePair<T>> WithIndex<T>(this IEnumerable<T> source)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        return WithIndexIterator(source);
    }

    private static IEnumerable<IndexValuePair<T>> WithIndexIterator<T>(IEnumerable<T> source)
    {
        int position = 0;
        foreach (T value in source)
            yield return new IndexValuePair<T>(position++, value);
    }
}

public struct IndexValuePair<T>
{
    public IndexValuePair(int index, T value)
    {
        m_index = index;
        m_value = value;
    }

    public int Index
    {
        get { return m_index; }
    }
    public T Value
    {
        get { return m_value; }
    }

    readonly int m_index;
    readonly T m_value;
}
Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: