Implementing Linqs Select without the yield keyword. Cannot monitor control flow

I know a lot has been written about Linq and its internal developments. Inspired by Jon Skeets EduLinq, I wanted to demystify what happens behind the Linq operators. So I tried to implement the Linqs Select () method, which at first glance seems pretty boring. But actually I am trying to implement it without using the yield keyword.

So here is what I got so far:

class Program
{
    static void Main(string[] args)
    {
        var list = new int[] {1, 2, 3};

        var otherList = list.MySelect(x => x.ToString()).MySelect(x => x + "test");

        foreach (var item in otherList)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }
}

public static class EnumerableEx
{
    public static IEnumerable<R> MySelect<T, R>(this IEnumerable<T> sequence, Func<T, R> apply)
    {
        return new EnumerableWrapper<R, T>(sequence, apply);
    }
}

public class EnumerableWrapper<T, O> : IEnumerable<T>
{
    private readonly IEnumerable<O> _sequence;
    private readonly Func<O, T> _apply;

    public EnumerableWrapper(IEnumerable<O> sequence, Func<O, T> apply)
    {
        _sequence = sequence;
        _apply = apply;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new EnumeratorWrapper<T, O>(_sequence, _apply);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class EnumeratorWrapper<T, O> : IEnumerator<T>
{
    private readonly IEnumerator<O> _enumerator;
    private readonly Func<O, T> _apply;

    public EnumeratorWrapper(IEnumerable<O> sequence, Func<O, T> apply)
    {
        _enumerator = sequence.GetEnumerator();
        _apply = apply;
    }

    public void Dispose()
    {
    }

    public bool MoveNext()
    {
        var hasItems = _enumerator.MoveNext();
        if (hasItems)
            Current = _apply(_enumerator.Current);
        return hasItems;
    }

    public void Reset()
    {
        _enumerator.Reset();
    }

    public T Current { get; private set; }

    object IEnumerator.Current
    {
        get { return Current; }
    }
}

, . , . , . , ( !) MoveNext(). MoveNext(), , . , , . , , , , ?

+5
1

, MoveNext() , :

  • MoveNext() ( Y), ...
  • MoveNext() ( X), ...
  • MoveNext() (), .
  • MoveNext() X x => x.ToString(), Current
  • MoveNext() Y x => x + "test" X.Current Y.Current

, - , . , EnumeratorWrapper.MoveNext ; , , Main.

, , , , , . ( , , . !)

+5

All Articles