Tigraine

Daniel Hoelbling-Inzko talks about programming

Enumerators in C#

I am still trying to figure out if what I did was useful or not.

Based on the assumption that sometimes you may need a variable typed IEnumerable<T> to hold a value that only implements IEnumerable I wrote this adapter class (you find it after the jump).

What's IEnumerator?
IEnumerator it the old non-generic implementation of the Iterator pattern, while IEnumerator<T> is the strongly-typed generic version introduced in .NET 2.0.

IEnumerable<T> implements IEnumerable, but there is no way to cast IEnumerable to IEnumerable<T>. So I wondered how you could comply to the Iterator pattern.

My first suspicion came when I tried foreach on both IEnumerables. Foreach has no problem with both of them, so I dug out my C# language spec and discovered that foreach has to use two different methods for either IEnumerable or IEnumerable<T> (That's not really clear there, anyone to falsify my assumption?).
They could have gone the other way and use the non-generic IEnumerable for the iteration, but that would need an implicit typecast on every iteration (and that would slow things down I guess).

In a scenario like the following one you can't pass the Enumerator created by an Array.GetEnumerator() because it uses IEnumerator instead of the generic version IEnumerator<T>.

public void PrintList(IEnumerable<String> MyList)
{
  
foreach (String Entryin MyList)
    {
      
Console.WriteLine("{0}", Entry);
    }
}

Because IEnumerable<T> implements IEnumerable you could just switch back to the non-generic version, but that's something I don't really like (although it may be more practical).

So here are 2 (very simple) adapter classes that will provide upward-compatibility to your IEnumerable and IEnumerator needs:


public class GenericEnumerableAdapter<T> : IEnumerable<T>
{
    private IEnumerable _Old;
    
    public GenericEnumerableAdapter(IEnumerable OldEnumerable)
    {
        this._Old = OldEnumerable;
    }

#region IEnumerable<T> Members

public IEnumerator<T> GetEnumerator() { return new GenericEnumeratorAdapter<T>(_Old.GetEnumerator()); }

#endregion

#region IEnumerable Members

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

#endregion }

public class GenericEnumeratorAdapter<T> : IEnumerator<T> { private IEnumerator _OldEnum; public GenericEnumeratorAdapter(IEnumerator OldEnumerator) { _OldEnum = OldEnumerator; }

#region IDisposable Members

public void Dispose() { this._OldEnum = null; }

#endregion

#region IEnumerator<T> Members

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

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

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

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

#endregion }

My Photography business

Projects

dynamic css for .NET

Archives

more