Wednesday, January 19, 2011

Is it possible to advance an enumerator and get its value in a lambda?

If I have an IEnumerator variable is it possible to have a lambda function that takes it, advances it with MoveNext() and returns the Current value every single time its called?

  • A Lambda expression can contain complex statements, so you can do the following:

    Func<IEnumerator, object> f = ie => { ie.MoveNext(); return ie.Current; };
    
    George Mauer : thanks, just couldn't find the syntax
  • e => e.MoveNext() ? e.Current : null
    

    This will advance the enumerator and return the current value, and return null when the enumeration is complete.

    From Jonathan
  • Is this what you are looking for?

    List<string> strings = new List<string>()
    {
        "Hello", "I", "am", "a", "list", "of", "strings."
    };
    IEnumerator<string> e = strings.GetEnumerator();
    Func<string> f = () => e.MoveNext() ? e.Current : null;
    for (; ; )
    {
        string str = f();
        if (str == null)
            break;
    
        Console.Write(str + " ");
    }
    

    The point of an IEnumerator is that you already get syntactic sugar to deal with it:

    foreach (string str in strings)
        Console.Write(str + " ");
    

    Even handling the enumerator directly looks cleaner in this case:

    while (e.MoveNext())
        Console.Write(e.Current + " ");
    
    From fryguybob
  • Extending on Abe's solution, you can also use closures to hold a reference to the enumerator:

    var iter = ((IEnumerable<char>)"hello").GetEnumerator();
    
    //with closure
    {
        Func<object> f =
            () =>
                {
                    iter.MoveNext();
                    return iter.Current;
                };
        Console.WriteLine(f());
        Console.WriteLine(f());
    }
    
    //without closure
    {
        Func<IEnumerator, object> f =
            ie =>
                {
                    ie.MoveNext();
                    return ie.Current;
                };
        Console.WriteLine(f(iter));
        Console.WriteLine(f(iter));
    }
    

0 comments:

Post a Comment