Tigraine
Daniel Hoelbling talks about .NET

Converting a IEnumerator to IEnumerator<T>

October 11th, 2009 . by Daniel Hölbling

When generics where introduced with .NET 2.0 there was a ton of 1.1 code lying around that was still built without generics. So the obvious answer by Microsoft was that most generic specialization classes can be cast to their non-generic counterparts to avoid problems for users.

Now, years later we have the opposite phenomenon. Few people are actually using untyped collections, so a new problem has come: What if you are looking at legacy code that has to call into new API that has no non-generic support.

Well, it’s simple: IEnumerator becomes IEnumerator<object> and all is well. But there is no conversion from IEnumerator to IEnumerator<object>, so you have to write your own little facades when trying to put square blocks into round holes:

public class CastEnumerator<T> : IEnumerator<T>
{
    private readonly IEnumerator enumerator;

    public CastEnumerator(IEnumerator enumerator)
    {
        this.enumerator = enumerator;
    }

    public void Dispose()
    {
    }

    public bool MoveNext()
    {
        return enumerator.MoveNext();
    }

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

    public T Current
    {
        get { return (T)enumerator.Current; }
    }

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

The call then looks like this:

public IEnumerator<T> GetEnumerator()
{
    return new CastEnumerator<T>(untypedEnumerator);
}

As Julian Birch explained in the comments, if you are using .NET 3.5 it’s even simpler to get from an untyped IEnumerable to a IEnumerable<T> (while not technically a IEnumerator, the typed one will then return a IEnumerator<T>):

IEnumerable untypedEnumerable = ...;
IEnumerable<string> typedEnumerable = untypedEnumerable.Cast<T>();

  • JulianBirch
    If you're on 3.5, you can actually call Cast on an untyped enumerator.

    So you could write

    return untypedEnumerator.Cast<T>();
  • Oh thanks for the tip.
    I didn't look into 3.5 solutions since that particular problem cropped up in a 2.0 solution..

    greetings Daniel



    Update:
    Updated the post
blog comments powered by Disqus